diff --git a/.gitattributes b/.gitattributes index 2f356076d..8d1f26a78 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,8 +3,8 @@ # always use LF, even if the files are edited on windows, they need to be compiled/used on unix * text eol=lf -installation/mods_Abaqus/abaqus_v6_windows.env eol=crlf # Denote all files that are truly binary and should not be modified. *.png binary *.jpg binary *.cae binary +*.hdf5 binary diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index df5a10f60..6e82561c5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,7 @@ --- stages: - prepareAll + - python - preprocessing - postprocessing - compilePETSc @@ -103,6 +104,16 @@ checkout: - master - release +################################################################################################### +Pytest: + stage: python + script: + - cd $DAMASKROOT/python + - pytest + except: + - master + - release + ################################################################################################### OrientationRelationship: stage: preprocessing @@ -308,13 +319,6 @@ nonlocal_densityConservation: - master - release -Spectral_ipNeighborhood: - stage: grid - script: Spectral_ipNeighborhood/test.py - except: - - master - - release - RGC_DetectChanges: stage: grid script: RGC_DetectChanges/test.py @@ -506,7 +510,6 @@ Processing: stage: createDocumentation script: - cd $DAMASKROOT/processing/pre - - rm abq_addUserOutput.py marc_addUserOutput.py - $DAMASKROOT/PRIVATE/documenting/scriptHelpToWiki.py --debug *.py - cd $DAMASKROOT/processing/post - rm vtk2ang.py DAD*.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c9bbea04..3d53000d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ ######################################################################################## # Compiler options for building DAMASK -cmake_minimum_required (VERSION 3.6.0 FATAL_ERROR) +cmake_minimum_required (VERSION 3.10.0 FATAL_ERROR) #--------------------------------------------------------------------------------------- # Find PETSc from system environment diff --git a/PRIVATE b/PRIVATE index 214c69be8..524e86c11 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 214c69be8b51adb39eb7ad25b139727c8b98afce +Subproject commit 524e86c117d816e3bd873eed7663e258a6f2e139 diff --git a/VERSION b/VERSION index 442097b29..35ae2dc0f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.3-957-gccbcc0d0 +v2.0.3-1228-g3e269f04 diff --git a/examples/ConfigFiles/Crystallite_All.config b/examples/ConfigFiles/Crystallite_All.config deleted file mode 100644 index 2e9bafa73..000000000 --- a/examples/ConfigFiles/Crystallite_All.config +++ /dev/null @@ -1,9 +0,0 @@ -[all] -(output) orientation # quaternion -(output) grainrotation # deviation from initial orientation as axis (1-3) and angle in degree (4) in crystal reference coordinates -(output) F # deformation gradient tensor -(output) Fe # elastic deformation gradient tensor -(output) Fp # plastic deformation gradient tensor -(output) P # first Piola-Kichhoff stress tensor -(output) S # second Piola-Kichhoff stress tensor -(output) Lp # plastic velocity gradient tensor diff --git a/examples/ConfigFiles/Phase_Dislotwin_Tungsten.config b/examples/ConfigFiles/Phase_Dislotwin_Tungsten.config index b780f5c59..30c04cb9a 100644 --- a/examples/ConfigFiles/Phase_Dislotwin_Tungsten.config +++ b/examples/ConfigFiles/Phase_Dislotwin_Tungsten.config @@ -14,7 +14,7 @@ SolidSolutionStrength 1.5e8 # Strength due to elements in solid solution ### Dislocation glide parameters ### #per family -Nslip 12 0 +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] diff --git a/examples/ConfigFiles/Phase_Nonlocal_Aluminum.config b/examples/ConfigFiles/Phase_Nonlocal_Aluminum.config index 6406a47c0..fd18aa719 100644 --- a/examples/ConfigFiles/Phase_Nonlocal_Aluminum.config +++ b/examples/ConfigFiles/Phase_Nonlocal_Aluminum.config @@ -4,58 +4,23 @@ elasticity hooke plasticity nonlocal /nonlocal/ -(output) rho -(output) rho_edge -(output) rho_screw -(output) rho_sgl -(output) rho_sgl_edge_pos -(output) rho_sgl_edge_neg -(output) rho_sgl_screw_pos -(output) rho_sgl_screw_neg -(output) rho_sgl_edge_pos_mobile -(output) rho_sgl_edge_neg_mobile -(output) rho_sgl_screw_pos_mobile -(output) rho_sgl_screw_neg_mobile -(output) rho_sgl_edge_pos_immobile -(output) rho_sgl_edge_neg_immobile -(output) rho_sgl_screw_pos_immobile -(output) rho_sgl_screw_neg_immobile -(output) rho_dip_edge -(output) rho_dip_screw +(output) rho_sgl_mob_edg_pos +(output) rho_sgl_imm_edg_pos +(output) rho_sgl_mob_edg_neg +(output) rho_sgl_imm_edg_neg +(output) rho_sgl_mob_scr_pos +(output) rho_sgl_imm_scr_pos +(output) rho_sgl_mob_scr_neg +(output) rho_sgl_imm_scr_neg +(output) rho_dip_edg +(output) rho_dip_scr (output) rho_forest -(output) delta -(output) delta_sgl -(output) delta_dip -(output) shearrate -(output) resolvedstress -(output) resolvedstress_back -(output) resolvedstress_external -(output) resistance -(output) rho_dot -(output) rho_dot_sgl -(output) rho_dot_sgl_mobile -(output) rho_dot_dip -(output) rho_dot_gen_edge -(output) rho_dot_gen_screw -(output) rho_dot_sgl2dip_edge -(output) rho_dot_sgl2dip_screw -(output) rho_dot_ann_ath -(output) rho_dot_ann_the -(output) rho_dot_ann_the_edge -(output) rho_dot_ann_the_screw -(output) rho_dot_edgejogs -(output) rho_dot_flux -(output) rho_dot_flux_mobile -(output) rho_dot_flux_edge -(output) rho_dot_flux_screw -(output) velocity_edge_pos -(output) velocity_edge_neg -(output) velocity_screw_pos -(output) velocity_screw_neg -(output) maximumDipoleHeight_edge -(output) maximumDipoleHeight_screw -(output) accumulated_shear -(output) dislocationstress +(output) gamma +(output) tau_pass +(output) v_edg_pos +(output) v_edg_neg +(output) v_scr_pos +(output) v_scr_neg lattice_structure fcc Nslip 12 # number of slip systems diff --git a/examples/ConfigFiles/Phase_Nonlocal_Nickel.config b/examples/ConfigFiles/Phase_Nonlocal_Nickel.config index 3420b4246..3cba4d975 100644 --- a/examples/ConfigFiles/Phase_Nonlocal_Nickel.config +++ b/examples/ConfigFiles/Phase_Nonlocal_Nickel.config @@ -3,31 +3,24 @@ elasticity hooke plasticity nonlocal /nonlocal/ - -(output) rho -(output) rho_sgl_mobile -(output) rho_sgl_immobile -(output) rho_sgl_edge_pos -(output) rho_sgl_edge_neg -(output) rho_sgl_screw_pos -(output) rho_sgl_screw_neg -(output) rho_dip_edge -(output) rho_dip_screw +(output) rho_sgl_mob_edg_pos +(output) rho_sgl_imm_edg_pos +(output) rho_sgl_mob_edg_neg +(output) rho_sgl_imm_edg_neg +(output) rho_sgl_mob_scr_pos +(output) rho_sgl_imm_scr_pos +(output) rho_sgl_mob_scr_neg +(output) rho_sgl_imm_scr_neg +(output) rho_dip_edg +(output) rho_dip_scr (output) rho_forest -(output) accumulatedshear -(output) shearrate -(output) resolvedstress -(output) resistance -(output) velocity_edge_pos -(output) rho_dot_gen -(output) rho_dot_sgl2dip_edge -(output) rho_dot_sgl2dip_screw -(output) rho_dot_ann_ath -(output) rho_dot_ann_the_edge -(output) rho_dot_ann_the_screw -(output) rho_dot_edgejogs -(output) rho_dot_flux_edge -(output) rho_dot_flux_screw +(output) gamma +(output) tau_pass +(output) v_edg_pos +(output) v_edg_neg +(output) v_scr_pos +(output) v_scr_neg + lattice_structure fcc Nslip 12 # number of slip systems per family diff --git a/examples/SpectralMethod/Polycrystal/material.config b/examples/SpectralMethod/Polycrystal/material.config index 4570941aa..e47c2142c 100644 --- a/examples/SpectralMethod/Polycrystal/material.config +++ b/examples/SpectralMethod/Polycrystal/material.config @@ -5,18 +5,6 @@ [SX] mech none -#-------------------# - -#-------------------# -[almostAll] -(output) orientation # quaternion -(output) grainrotation # deviation from initial orientation as axis (1-3) and angle in degree (4) -(output) F # deformation gradient tensor -(output) Fe # elastic deformation gradient tensor -(output) Fp # plastic deformation gradient tensor -(output) P # first Piola-Kichhoff stress tensor -(output) Lp # plastic velocity gradient tensor - #-------------------# #-------------------# diff --git a/installation/mods_MarcMentat/2018.1/Marc_tools/include_linux64 b/installation/mods_MarcMentat/2018.1/Marc_tools/include_linux64 index 538434ad0..10a796e47 100644 --- a/installation/mods_MarcMentat/2018.1/Marc_tools/include_linux64 +++ b/installation/mods_MarcMentat/2018.1/Marc_tools/include_linux64 @@ -546,15 +546,15 @@ fi # DAMASK compiler calls: additional flags are in line 2 OpenMP flags in line 3 -DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -O0 $I8FFLAGS -I$MARC_SOURCE/common \ +DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" -DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -O1 $I8FFLAGS -I$MARC_SOURCE/common \ +DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" -DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -fno-alias -O2 $I8FFLAGS -I$MARC_SOURCE/common \ +DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" @@ -572,20 +572,6 @@ then $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM" fi - # DAMASK compiler calls: additional flags are in line 2 OpenMP flags in line 3 - DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" - DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" - DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -fno-alias $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" - FORTLOWT="$FORTLOW" FORTRANT="$FORTRAN" diff --git a/installation/mods_MarcMentat/2018/Marc_tools/include_linux64 b/installation/mods_MarcMentat/2018/Marc_tools/include_linux64 index d3151ac6c..694dccee3 100644 --- a/installation/mods_MarcMentat/2018/Marc_tools/include_linux64 +++ b/installation/mods_MarcMentat/2018/Marc_tools/include_linux64 @@ -546,15 +546,15 @@ fi # DAMASK compiler calls: additional flags are in line 2 OpenMP flags in line 3 -DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -O0 $I8FFLAGS -I$MARC_SOURCE/common \ +DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" -DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -O1 $I8FFLAGS -I$MARC_SOURCE/common \ +DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" -DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -fno-alias -O2 $I8FFLAGS -I$MARC_SOURCE/common \ +DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" @@ -572,20 +572,6 @@ then $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM" fi - # DAMASK compiler calls: additional flags are in line 2 OpenMP flags in line 3 - DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" - DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" - DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -fno-alias $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" - FORTLOWT="$FORTLOW" FORTRANT="$FORTRAN" diff --git a/installation/mods_MarcMentat/2019/Marc_tools/include_linux64 b/installation/mods_MarcMentat/2019/Marc_tools/include_linux64 index 290055ed3..6d630bd1d 100644 --- a/installation/mods_MarcMentat/2019/Marc_tools/include_linux64 +++ b/installation/mods_MarcMentat/2019/Marc_tools/include_linux64 @@ -554,16 +554,16 @@ fi # DAMASK compiler calls: additional flags are in line 2 OpenMP flags in line 3 -DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -O0 $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ +DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ + -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2019 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" -DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -O1 $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ +DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ + -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2019 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" -DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -fno-alias -O2 $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ +DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ + -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2019 -DDAMASKVERSION=$DAMASKVERSION \ -qopenmp -qopenmp-threadprivate=compat\ $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" @@ -579,19 +579,6 @@ then $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM" fi - # DAMASK compiler calls: additional flags are in line 2 OpenMP flags in line 3 - DFORTLOWMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" - DFORTRANMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" - DFORTHIGHMP="$FCOMP -c -implicitnone -stand f08 -standard-semantics -assume nostd_mod_proc_name -safe_cray_ptr $PROFILE -zero -mp1 -WB -fno-alias $I8FFLAGS -I$MARC_SOURCE/common \ - -fpp -ftz -diag-disable 5268 -warn declarations -warn general -warn usage -warn interfaces -warn ignore_loc -warn alignments -DMarc4DAMASK=2018.1 -DDAMASKVERSION=$DAMASKVERSION \ - -qopenmp -qopenmp-threadprivate=compat\ - $MUMPS_INCLUDE $I8DEFINES -DLinux -DLINUX -DLinux_intel $FDEFINES $DDM $SOLVERFLAGS -I$KDTREE2_MOD" FORTLOWT="$FORTLOW" FORTRANT="$FORTRAN" diff --git a/processing/misc/gwyddion_filter.py b/processing/misc/gwyddion_filter.py deleted file mode 100755 index d5b1e39f0..000000000 --- a/processing/misc/gwyddion_filter.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import os,string,scipy -import numpy as np -import damask -from optparse import OptionParser - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Apply filter(s) to Gwyddion data. -""" + string.replace(scriptID,'\n','\\n') -) - -for option in ['opening', - 'closing', - 'erosion', - 'dilation', - 'average', - 'median', - ]: - parser.add_option('-%s'%option[0], '--%s'%option, dest=option, type='int', - help = 'stencil size for %s filter'%option) - parser.set_default(option, 0) - -(options, filenames) = parser.parse_args() - - -# ------------------------------------------ read Gwyddion data --------------------------------------- - -for file in filenames: - filters = '' - header = [] - with open(file,'r') as f: - for line in f: - pieces = line.split() - if pieces[0] != '#': break - if pieces[1] == 'Width:': width = float(pieces[2]) - if pieces[1] == 'Height:': height = float(pieces[2]) - header.append(line.lstrip('#').strip()) - - elevation = np.loadtxt(file)#*1e6 - - if options.opening > 0: - elevation = scipy.ndimage.morphology.grey_opening(elevation,options.opening) - filters += '_opening%i'%options.opening - if options.closing > 0: - elevation = scipy.ndimage.morphology.grey_closing(elevation,options.closing) - filters += '_closing%i'%options.closing - if options.erosion > 0: - elevation = scipy.ndimage.morphology.grey_erosion(elevation,options.erosion) - filters += '_erosion%i'%options.erosion - if options.dilation > 0: - elevation = scipy.ndimage.morphology.grey_dilation(elevation,options.dilation) - filters += '_dilation%i'%options.dilation - if options.average > 0: - elevation = scipy.ndimage.filters.uniform_filter(elevation,options.average) - filters += '_avg%i'%options.average - if options.median > 0: - elevation = scipy.ndimage.filters.median_filter(elevation,options.median) - filters += '_median%i'%options.median - - np.savetxt(os.path.splitext(file)[0]+filters+os.path.splitext(file)[1],elevation,header='\n'.join(header)) - diff --git a/processing/misc/vtk_fromGwyddion.py b/processing/misc/vtk_fromGwyddion.py deleted file mode 100755 index e64bf4393..000000000 --- a/processing/misc/vtk_fromGwyddion.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import os,string,vtk -import numpy as np -import damask -from optparse import OptionParser - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -scalingFactor = { \ - 'm': { - 'm': 1e0, - 'mm': 1e-3, - 'µm': 1e-6, - }, - 'mm': { - 'm': 1e+3, - 'mm': 1e0, - 'µm': 1e-3, - }, - 'µm': { - 'm': 1e+6, - 'mm': 1e+3, - 'µm': 1e0, - }, - } - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Produce VTK rectilinear grid from Gwyddion dataset exported as text. -""" + string.replace(scriptID,'\n','\\n') -) - -parser.add_option('-s', '--scaling', dest='scaling', type='float', - help = 'scaling factor for elevation data [auto]') - -parser.set_defaults(scaling = 0.0) - -(options, filenames) = parser.parse_args() - - -# ------------------------------------------ read Gwyddion data --------------------------------------- - -for file in filenames: - with open(file,'r') as f: - for line in f: - pieces = line.split() - if pieces[0] != '#': break - if len(pieces) < 2: continue - if pieces[1] == 'Width:': - width = float(pieces[2]) - lateralunit = pieces[3] - if pieces[1] == 'Height:': - height = float(pieces[2]) - lateralunit = pieces[3] - if pieces[1] == 'Value' and pieces[2] == 'units:': - elevationunit = pieces[3] - - if options.scaling == 0.0: - options.scaling = scalingFactor[lateralunit][elevationunit] - - elevation = np.loadtxt(file)*options.scaling - - grid = vtk.vtkRectilinearGrid() - grid.SetDimensions(elevation.shape[1],elevation.shape[0],1) - - xCoords = vtk.vtkDoubleArray() - for x in np.arange(0.0,width,width/elevation.shape[1],'d'): - xCoords.InsertNextValue(x) - yCoords = vtk.vtkDoubleArray() - for y in np.arange(0.0,height,height/elevation.shape[0],'d'): - yCoords.InsertNextValue(y) - zCoords = vtk.vtkDoubleArray() - zCoords.InsertNextValue(0.0) - - grid.SetXCoordinates(xCoords) - grid.SetYCoordinates(yCoords) - grid.SetZCoordinates(zCoords) - - vector = vtk.vtkFloatArray() - vector.SetName("elevation"); - vector.SetNumberOfComponents(3); - vector.SetNumberOfTuples(np.prod(elevation.shape)); - for i,z in enumerate(np.ravel(elevation)): - vector.SetTuple3(i,0,0,z) - - grid.GetPointData().AddArray(vector) - - writer = vtk.vtkXMLRectilinearGridWriter() - writer.SetDataModeToBinary() - writer.SetCompressorTypeToZLib() - writer.SetFileName(os.path.splitext(file)[0]+'.vtr') - if vtk.VTK_MAJOR_VERSION <= 5: - writer.SetInput(grid) - else: - writer.SetInputData(grid) - writer.Write() diff --git a/processing/post/DADF5_postResults.py b/processing/post/DADF5_postResults.py index 0db018173..efbf84b98 100755 --- a/processing/post/DADF5_postResults.py +++ b/processing/post/DADF5_postResults.py @@ -47,6 +47,8 @@ for filename in options.filenames: coords = np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3) + N_digits = int(np.floor(np.log10(int(results.increments[-1][3:]))))+1 + N_digits = 5 # hack to keep test intact for i,inc in enumerate(results.iter_visible('increments')): print('Output step {}/{}'.format(i+1,len(results.increments))) @@ -59,38 +61,39 @@ for filename in options.filenames: data = np.concatenate((data,coords),1) header+=' 1_pos 2_pos 3_pos' + results.set_visible('materialpoints',False) + results.set_visible('constituents', True) for label in options.con: - for p in results.iter_visible('con_physics'): - for c in results.iter_visible('constituents'): - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - d = int(np.product(np.shape(array)[1:])) - data = np.concatenate((data,np.reshape(array,[np.product(results.grid),d])),1) - - if d>1: - header+= ''.join([' {}_{}'.format(j+1,label) for j in range(d)]) - else: - header+=' '+label + x = results.get_dataset_location(label) + if len(x) == 0: + continue + array = results.read_dataset(x,0,plain=True) + d = np.product(np.shape(array)[1:]) + data = np.concatenate((data,np.reshape(array,[np.product(results.grid),d])),1) + if d>1: + header+= ''.join([' {}_{}'.format(j+1,label) for j in range(d)]) + else: + header+=' '+label + + results.set_visible('constituents', False) + results.set_visible('materialpoints',True) for label in options.mat: - for p in results.iter_visible('mat_physics'): - for m in results.iter_visible('materialpoints'): - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - d = int(np.product(np.shape(array)[1:])) - data = np.concatenate((data,np.reshape(array,[np.product(results.grid),d])),1) + x = results.get_dataset_location(label) + if len(x) == 0: + continue + array = results.read_dataset(x,0,plain=True) + d = np.product(np.shape(array)[1:]) + data = np.concatenate((data,np.reshape(array,[np.product(results.grid),d])),1) - if d>1: - header+= ''.join([' {}_{}'.format(j+1,label) for j in range(d)]) - else: - header+=' '+label + if d>1: + header+= ''.join([' {}_{}'.format(j+1,label) for j in range(d)]) + else: + header+=' '+label dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) if not os.path.isdir(dirname): os.mkdir(dirname,0o755) - file_out = '{}_{}.txt'.format(os.path.splitext(os.path.split(filename)[-1])[0],inc) + file_out = '{}_inc{}.txt'.format(os.path.splitext(os.path.split(filename)[-1])[0], + inc[3:].zfill(N_digits)) np.savetxt(os.path.join(dirname,file_out),data,header=header,comments='') diff --git a/processing/post/DADF5_vtk_cells.py b/processing/post/DADF5_vtk_cells.py index 915479e26..b8875f4e9 100755 --- a/processing/post/DADF5_vtk_cells.py +++ b/processing/post/DADF5_vtk_cells.py @@ -42,7 +42,7 @@ for filename in options.filenames: results = damask.DADF5(filename) if results.structured: # for grid solvers use rectilinear grid - grid = vtk.vtkRectilineagrid() + grid = vtk.vtkRectilinearGrid() coordArray = [vtk.vtkDoubleArray(), vtk.vtkDoubleArray(), vtk.vtkDoubleArray(), @@ -66,7 +66,7 @@ for filename in options.filenames: for i in f['/geometry/T_c']: grid.InsertNextCell(vtk.VTK_HEXAHEDRON,8,i-1) - + N_digits = int(np.floor(np.log10(int(results.increments[-1][3:]))))+1 for i,inc in enumerate(results.iter_visible('increments')): print('Output step {}/{}'.format(i+1,len(results.increments))) vtk_data = [] @@ -74,7 +74,6 @@ for filename in options.filenames: results.set_visible('materialpoints',False) results.set_visible('constituents', True) for label in options.con: - for p in results.iter_visible('con_physics'): if p != 'generic': for c in results.iter_visible('constituents'): @@ -98,7 +97,7 @@ for filename in options.filenames: results.set_visible('constituents', False) results.set_visible('materialpoints',True) - for label in options.mat: + for label in options.mat: for p in results.iter_visible('mat_physics'): if p != 'generic': for m in results.iter_visible('materialpoints'): @@ -120,14 +119,22 @@ for filename in options.filenames: vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) grid.GetCellData().AddArray(vtk_data[-1]) - writer = vtk.vtkXMLRectilineagridWriter() if results.structured else \ + writer = vtk.vtkXMLRectilinearGridWriter() if results.structured else \ vtk.vtkXMLUnstructuredGridWriter() - + results.set_visible('constituents', False) + results.set_visible('materialpoints',False) + x = results.get_dataset_location('u_n') + vtk_data.append(numpy_support.numpy_to_vtk(num_array=results.read_dataset(x,0),deep=True,array_type=vtk.VTK_DOUBLE)) + vtk_data[-1].SetName('u') + grid.GetPointData().AddArray(vtk_data[-1]) + dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) if not os.path.isdir(dirname): os.mkdir(dirname,0o755) - file_out = '{}_{}.{}'.format(os.path.splitext(os.path.split(filename)[-1])[0],inc,writer.GetDefaultFileExtension()) + file_out = '{}_inc{}.{}'.format(os.path.splitext(os.path.split(filename)[-1])[0], + inc[3:].zfill(N_digits), + writer.GetDefaultFileExtension()) writer.SetCompressorTypeToZLib() writer.SetDataModeToBinary() diff --git a/processing/post/DADF5_vtk_points.py b/processing/post/DADF5_vtk_points.py index 87c1ad93e..9265cc3a0 100755 --- a/processing/post/DADF5_vtk_points.py +++ b/processing/post/DADF5_vtk_points.py @@ -52,6 +52,7 @@ for filename in options.filenames: Polydata.SetVerts(Vertices) Polydata.Modified() + N_digits = int(np.floor(np.log10(int(results.increments[-1][3:]))))+1 for i,inc in enumerate(results.iter_visible('increments')): print('Output step {}/{}'.format(i+1,len(results.increments))) vtk_data = [] @@ -111,7 +112,9 @@ for filename in options.filenames: dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) if not os.path.isdir(dirname): os.mkdir(dirname,0o755) - file_out = '{}_{}.{}'.format(os.path.splitext(os.path.split(filename)[-1])[0],inc,writer.GetDefaultFileExtension()) + file_out = '{}_inc{}.{}'.format(os.path.splitext(os.path.split(filename)[-1])[0], + inc[3:].zfill(N_digits), + writer.GetDefaultFileExtension()) writer.SetCompressorTypeToZLib() writer.SetDataModeToBinary() diff --git a/processing/post/DADF5toDREAM3D.py b/processing/post/DADF5toDREAM3D.py index 885545297..7ab04b934 100755 --- a/processing/post/DADF5toDREAM3D.py +++ b/processing/post/DADF5toDREAM3D.py @@ -49,7 +49,7 @@ Phase_types = {'Primary': 0} #further additions to these can be done by looking # -------------------------------------------------------------------- parser = argparse.ArgumentParser(description='Creating a file for DREAM3D from DAMASK data') parser.add_argument('filenames',nargs='+',help='HDF5 based output file') -parser.add_argument('--inc',nargs='+',help='Increment for which DREAM3D to be used, eg. 00025',type=int) +parser.add_argument('--inc',nargs='+',help='Increment for which DREAM3D to be used, eg. 25',type=int) parser.add_argument('-d','--dir', dest='dir',default='postProc',metavar='string', help='name of subdirectory to hold output') @@ -59,15 +59,13 @@ options = parser.parse_args() # loop over input files for filename in options.filenames: f = damask.DADF5(filename) #DAMASK output file - count = 0 - for increment in f.increments: - if int(increment[3:]) not in options.inc: - count = count + 1 + for increment in options.inc: + f.set_by_increment(increment,increment) + if len(f.visible['increments']) == 0: continue #-------output file creation------------------------------------- dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) - print(dirname) try: os.mkdir(dirname) except FileExistsError: @@ -90,11 +88,10 @@ for filename in options.filenames: # Phase information of DREAM.3D is constituent ID in DAMASK o[cell_data_label + '/Phases'] = f.get_constituent_ID().reshape(tuple(f.grid)+(1,)) # Data quaternions - DAMASK_quaternion = f.read_dataset(f.get_dataset_location('orientation'),0) - DREAM_3D_quaternion = np.empty((np.prod(f.grid),4),dtype=np.float32) + DAMASK_quaternion = f.read_dataset(f.get_dataset_location('orientation')) # Convert: DAMASK uses P = -1, DREAM.3D uses P = +1. Also change position of imagninary part DREAM_3D_quaternion = np.hstack((-DAMASK_quaternion['x'],-DAMASK_quaternion['y'],-DAMASK_quaternion['z'], - DAMASK_quaternion['w'])) + DAMASK_quaternion['w'])).astype(np.float32) o[cell_data_label + '/Quats'] = DREAM_3D_quaternion.reshape(tuple(f.grid)+(4,)) # Attributes to CellData group @@ -109,12 +106,14 @@ for filename in options.filenames: # phase attributes o[cell_data_label + '/Phases'].attrs['ComponentDimensions'] = np.array([1],np.uint64) o[cell_data_label + '/Phases'].attrs['ObjectType'] = 'DataArray' + o[cell_data_label + '/Phases'].attrs['TupleDimensions'] = f.grid.astype(np.uint64) # Quats attributes o[cell_data_label + '/Quats'].attrs['ComponentDimensions'] = np.array([4],np.uint64) o[cell_data_label + '/Quats'].attrs['ObjectType'] = 'DataArray' - - # Create EnsembleAttributeMatrix + o[cell_data_label + '/Quats'].attrs['TupleDimensions'] = f.grid.astype(np.uint64) + + # Create EnsembleAttributeMatrix ensemble_label = data_container_label + '/EnsembleAttributeMatrix' # Data CrystalStructures diff --git a/processing/post/addCauchy.py b/processing/post/addCauchy.py index 18c4ec215..afc5a57be 100755 --- a/processing/post/addCauchy.py +++ b/processing/post/addCauchy.py @@ -2,10 +2,9 @@ import os import sys +from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -36,54 +35,15 @@ parser.set_defaults(defgrad = 'f', ) (options,filenames) = parser.parse_args() - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, buffered = False) - except: - continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + table.add('Cauchy', + damask.mechanics.Cauchy(table.get(options.defgrad).reshape(-1,3,3), + table.get(options.stress ).reshape(-1,3,3)).reshape(-1,9), + scriptID+' '+' '.join(sys.argv[1:])) - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - column = {} - - for tensor in [options.defgrad,options.stress]: - dim = table.label_dimension(tensor) - if dim < 0: errors.append('column {} not found.'.format(tensor)) - elif dim != 9: errors.append('column {} is not a tensor.'.format(tensor)) - else: - column[tensor] = table.label_index(tensor) - - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(['{}_Cauchy'.format(i+1) for i in range(9)]) # extend ASCII header with new labels - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - F = np.array(list(map(float,table.data[column[options.defgrad]:column[options.defgrad]+9])),'d').reshape(3,3) - P = np.array(list(map(float,table.data[column[options.stress ]:column[options.stress ]+9])),'d').reshape(3,3) - table.data_append(list(1.0/np.linalg.det(F)*np.dot(P,F.T).reshape(9))) # [Cauchy] = (1/det(F)) * [P].[F_transpose] - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addDeterminant.py b/processing/post/addDeterminant.py index 14f0321be..f2368559d 100755 --- a/processing/post/addDeterminant.py +++ b/processing/post/addDeterminant.py @@ -2,22 +2,16 @@ import os import sys +from io import StringIO from optparse import OptionParser +import numpy as np + import damask - scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -def determinant(m): - return +m[0]*m[4]*m[8] \ - +m[1]*m[5]*m[6] \ - +m[2]*m[3]*m[7] \ - -m[2]*m[4]*m[6] \ - -m[1]*m[3]*m[8] \ - -m[0]*m[5]*m[7] - # -------------------------------------------------------------------- # MAIN @@ -34,61 +28,18 @@ parser.add_option('-t','--tensor', help = 'heading of columns containing tensor field values') (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] if options.tensor is None: parser.error('no data column specified.') -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for tensor in options.tensor: + table.add('det({})'.format(tensor), + np.linalg.det(table.get(tensor).reshape(-1,3,3)), + scriptID+' '+' '.join(sys.argv[1:])) - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - items = { - 'tensor': {'dim': 9, 'shape': [3,3], 'labels':options.tensor, 'column': []}, - } - errors = [] - remarks = [] - - for type, data in items.items(): - for what in data['labels']: - dim = table.label_dimension(what) - if dim != data['dim']: remarks.append('column {} is not a {}...'.format(what,type)) - else: - items[type]['column'].append(table.label_index(what)) - table.labels_append('det({})'.format(what)) # extend ASCII header with new labels - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - for type, data in items.items(): - for column in data['column']: - table.data_append(determinant(list(map(float,table.data[column: column+data['dim']])))) - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addDeviator.py b/processing/post/addDeviator.py index c9aeaacfd..ca06034b3 100755 --- a/processing/post/addDeviator.py +++ b/processing/post/addDeviator.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import damask @@ -9,17 +10,6 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -oneThird = 1.0/3.0 - -def deviator(m,spherical = False): # Careful, do not change the value of m, its intent(inout)! - sph = oneThird*(m[0]+m[4]+m[8]) - dev = [ - m[0]-sph, m[1], m[2], - m[3], m[4]-sph, m[5], - m[6], m[7], m[8]-sph, - ] - return dev,sph if spherical else dev - # -------------------------------------------------------------------- # MAIN @@ -40,67 +30,22 @@ parser.add_option('-s','--spherical', help = 'report spherical part of tensor (hydrostatic component, pressure)') (options,filenames) = parser.parse_args() - -if options.tensor is None: - parser.error('no data column specified...') - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if options.tensor is None: + parser.error('no data column specified...') + for name in filenames: - try: - table = damask.ASCIItable(name = name, buffered = False) - except: - continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) + + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for tensor in options.tensor: + table.add('dev({})'.format(tensor), + damask.mechanics.deviatoric_part(table.get(tensor).reshape(-1,3,3)).reshape((-1,9)), + scriptID+' '+' '.join(sys.argv[1:])) + if options.spherical: + table.add('sph({})'.format(tensor), + damask.mechanics.spherical_part(table.get(tensor).reshape(-1,3,3)), + scriptID+' '+' '.join(sys.argv[1:])) -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - items = { - 'tensor': {'dim': 9, 'shape': [3,3], 'labels':options.tensor, 'active':[], 'column': []}, - } - errors = [] - remarks = [] - column = {} - - for type, data in items.items(): - for what in data['labels']: - dim = table.label_dimension(what) - if dim != data['dim']: remarks.append('column {} is not a {}.'.format(what,type)) - else: - items[type]['active'].append(what) - items[type]['column'].append(table.label_index(what)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - for type, data in items.items(): - for label in data['active']: - table.labels_append(['{}_dev({})'.format(i+1,label) for i in range(data['dim'])] + \ - (['sph({})'.format(label)] if options.spherical else [])) # extend ASCII header with new labels - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - for type, data in items.items(): - for column in data['column']: - table.data_append(deviator(list(map(float,table.data[column: - column+data['dim']])),options.spherical)) - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addInfo.py b/processing/post/addInfo.py index 2d8192cc1..5e32510db 100755 --- a/processing/post/addInfo.py +++ b/processing/post/addInfo.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 import os +import sys +from io import StringIO from optparse import OptionParser import damask @@ -24,35 +26,16 @@ parser.add_option('-i', dest = 'info', action = 'extend', metavar = '', help = 'items to add') - (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] if options.info is None: parser.error('no info specified.') -# --- loop over input files ------------------------------------------------------------------------ - -if filenames == []: filenames = [None] - for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ assemble header --------------------------------------- + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + table.comments += options.info - table.head_read() - table.info_append(options.info) - table.head_write() - -# ------------------------------------------ pass through data ------------------------------------- - - outputAlive = True - - while outputAlive and table.data_read(): # read next data line of ASCII table - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addMises.py b/processing/post/addMises.py index be11b0f1c..0c2a6db50 100755 --- a/processing/post/addMises.py +++ b/processing/post/addMises.py @@ -2,10 +2,8 @@ import os import sys +from io import StringIO from optparse import OptionParser -from collections import OrderedDict - -import numpy as np import damask @@ -13,15 +11,6 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -def Mises(what,tensor): - - dev = tensor - np.trace(tensor)/3.0*np.eye(3) - symdev = 0.5*(dev+dev.T) - return np.sqrt(np.sum(symdev*symdev.T)* - { - 'stress': 3.0/2.0, - 'strain': 2.0/3.0, - }[what.lower()]) # -------------------------------------------------------------------- # MAIN @@ -47,62 +36,21 @@ parser.set_defaults(strain = [], (options,filenames) = parser.parse_args() if options.stress is [] and options.strain is []: - parser.error('no data column specified...') - -# --- loop over input files ------------------------------------------------------------------------- + parser.error('no data column specified...') if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - items = OrderedDict([ - ('strain', {'dim': 9, 'shape': [3,3], 'labels':options.strain, 'active':[], 'column': []}), - ('stress', {'dim': 9, 'shape': [3,3], 'labels':options.stress, 'active':[], 'column': []}) - ]) - errors = [] - remarks = [] - - for type, data in items.items(): - for what in data['labels']: - dim = table.label_dimension(what) - if dim != data['dim']: remarks.append('column {} is not a {}...'.format(what,type)) - else: - items[type]['active'].append(what) - items[type]['column'].append(table.label_index(what)) - table.labels_append('Mises({})'.format(what)) # extend ASCII header with new labels - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - for type, data in items.items(): - for column in data['column']: - table.data_append(Mises(type, - np.array(table.data[column:column+data['dim']],'d').reshape(data['shape']))) - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for strain in options.strain: + table.add('Mises({})'.format(strain), + damask.mechanics.Mises_strain(damask.mechanics.symmetric(table.get(strain).reshape(-1,3,3))), + scriptID+' '+' '.join(sys.argv[1:])) + for stress in options.stress: + table.add('Mises({})'.format(stress), + damask.mechanics.Mises_stress(damask.mechanics.symmetric(table.get(stress).reshape(-1,3,3))), + scriptID+' '+' '.join(sys.argv[1:])) + + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addPK2.py b/processing/post/addPK2.py index f38753619..185160d79 100755 --- a/processing/post/addPK2.py +++ b/processing/post/addPK2.py @@ -2,10 +2,9 @@ import os import sys +from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -36,53 +35,16 @@ parser.set_defaults(defgrad = 'f', ) (options,filenames) = parser.parse_args() - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) - table.head_read() + table.add('S', + damask.mechanics.PK2(table.get(options.defgrad).reshape(-1,3,3), + table.get(options.stress ).reshape(-1,3,3)).reshape(-1,9), + scriptID+' '+' '.join(sys.argv[1:])) -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - column = {} - - for tensor in [options.defgrad,options.stress]: - dim = table.label_dimension(tensor) - if dim < 0: errors.append('column {} not found.'.format(tensor)) - elif dim != 9: errors.append('column {} is not a tensor.'.format(tensor)) - else: - column[tensor] = table.label_index(tensor) - - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(['{}_S'.format(i+1) for i in range(9)]) # extend ASCII header with new labels - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - F = np.array(list(map(float,table.data[column[options.defgrad]:column[options.defgrad]+9])),'d').reshape(3,3) - P = np.array(list(map(float,table.data[column[options.stress ]:column[options.stress ]+9])),'d').reshape(3,3) - table.data_append(list(np.dot(np.linalg.inv(F),P).reshape(9))) # [S] =[P].[F-1] - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/mentat_colorMap.py b/processing/post/mentat_colorMap.py deleted file mode 100755 index 7f5c67123..000000000 --- a/processing/post/mentat_colorMap.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import os -import sys -from optparse import OptionParser - -import damask - - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -# ----------------------------- -def outMentat(cmd,locals): - if cmd[0:3] == '(!)': - exec(cmd[3:]) - elif cmd[0:3] == '(?)': - cmd = eval(cmd[3:]) - py_mentat.py_send(cmd) - else: - py_mentat.py_send(cmd) - return - - - -# ----------------------------- -def outStdout(cmd,locals): - if cmd[0:3] == '(!)': - exec(cmd[3:]) - elif cmd[0:3] == '(?)': - cmd = eval(cmd[3:]) - print(cmd) - else: - print(cmd) - return - - - -# ----------------------------- -def output(cmds,locals,dest): - for cmd in cmds: - if isinstance(cmd,list): - output(cmd,locals,dest) - else: - {\ - 'Mentat': outMentat,\ - 'Stdout': outStdout,\ - }[dest](cmd,locals) - return - - - -# ----------------------------- -def colorMap(colors,baseIdx=32): - cmds = [ "*color %i %f %f %f"%(idx+baseIdx,color[0],color[1],color[2]) - for idx,color in enumerate(colors) ] - return cmds - - -# ----------------------------- -# MAIN FUNCTION STARTS HERE -# ----------------------------- - -parser = OptionParser(option_class=damask.extendableOption, -usage="%prog [options] predefinedScheme | (lower_h,s,l upper_h,s,l)", description = """ -Changes the color map in MSC.Mentat. - -Interpolates colors between "lower_hsl" and "upper_hsl". - -""", version = scriptID) - -parser.add_option("-i","--inverse", action = "store_true", - dest = "inverse", - help = "invert legend") -parser.add_option( "--palette", action = "store_true", - dest = "palette", - help = "output plain rgb palette integer values (0-255)") -parser.add_option( "--palettef", action = "store_true", - dest = "palettef", - help = "output plain rgb palette float values (0.0-1.0)") -parser.add_option("-p", "--port", type = "int", - dest = "port", - metavar ='int', - help = "Mentat connection port [%default]") -parser.add_option("-b", "--baseindex", type = "int", - metavar ='int', - dest = "baseIdx", - help = "base index of colormap [%default]") -parser.add_option("-n", "--colorcount", type = "int", - metavar ='int', - dest = "colorcount", - help = "number of colors [%default]") -parser.add_option("-v", "--verbose", action="store_true", - dest = "verbose", - help = "write Mentat command stream also to STDOUT") - -parser.set_defaults(port = 40007) -parser.set_defaults(baseIdx = 32) -parser.set_defaults(colorcount = 32) -parser.set_defaults(inverse = False) -parser.set_defaults(palette = False) -parser.set_defaults(palettef = False) -parser.set_defaults(verbose = False) - -msg = [] - -(options, colors) = parser.parse_args() - -if len(colors) == 0: - parser.error('missing color information') - -elif len(colors) == 1: - theMap = damask.Colormap(predefined = colors[0]) - -elif len(colors) == 2: - theMap = damask.Colormap(damask.Color('HSL',map(float, colors[0].split(','))), - damask.Color('HSL',map(float, colors[1].split(','))) ) - -else: - theMap = damask.Colormap() - -if options.inverse: - theMap = theMap.invert() - -if options.palettef: - print(theMap.export(format='raw',steps=options.colorcount)) -elif options.palette: - for theColor in theMap.export(format='list',steps=options.colorcount): - print('\t'.join(map(lambda x: str(int(255*x)),theColor))) -else: # connect to Mentat and change colorMap - sys.path.append(damask.solver.Marc().libraryPath()) - try: - import py_mentat - print('waiting to connect...') - py_mentat.py_connect('',options.port) - print('connected...') - mentat = True - except: - sys.stderr.write('warning: no valid Mentat release found\n') - mentat = False - - outputLocals = {} - cmds = colorMap(theMap.export(format='list',steps=options.colorcount),options.baseIdx) - if mentat: - output(['*show_table']+cmds+['*show_model *redraw'],outputLocals,'Mentat') - py_mentat.py_disconnect() - - if options.verbose: - output(cmds,outputLocals,'Stdout') diff --git a/processing/post/reLabel.py b/processing/post/reLabel.py index e7ad1f1e9..85d16acea 100755 --- a/processing/post/reLabel.py +++ b/processing/post/reLabel.py @@ -2,8 +2,8 @@ import os import sys +from io import StringIO from optparse import OptionParser -import re import damask @@ -35,62 +35,18 @@ parser.set_defaults(label = [], ) (options,filenames) = parser.parse_args() - -pattern = [re.compile('^()(.+)$'), # label pattern for scalar - re.compile('^(\d+_)?(.+)$'), # label pattern for multidimension - ] - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if len(options.label) != len(options.substitute): + parser.error('number of column labels and substitutes do not match.') + for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for i,label in enumerate(options.label): + table.rename(label, + options.substitute[i], + scriptID+' '+' '.join(sys.argv[1:])) - table.head_read() - -# ------------------------------------------ process labels --------------------------------------- - - errors = [] - remarks = [] - - if len(options.label) == 0: - errors.append('no labels specified.') - elif len(options.label) != len(options.substitute): - errors.append('mismatch between number of labels ({}) and substitutes ({}).'.format(len(options.label), - len(options.substitute))) - else: - indices = table.label_index (options.label) - dimensions = table.label_dimension(options.label) - for i,index in enumerate(indices): - if index == -1: remarks.append('label "{}" not present...'.format(options.label[i])) - else: - m = pattern[int(dimensions[i]>1)].match(table.tags[index]) # isolate label name - for j in range(dimensions[i]): - table.tags[index+j] = table.tags[index+j].replace(m.group(2),options.substitute[i]) # replace name with substitute - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/scaleData.py b/processing/post/scaleData.py index 5b03f8e07..58f853251 100755 --- a/processing/post/scaleData.py +++ b/processing/post/scaleData.py @@ -2,10 +2,9 @@ import os import sys +from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -23,7 +22,7 @@ Uniformly scale column values by given factor. """, version = scriptID) parser.add_option('-l','--label', - dest = 'label', + dest = 'labels', action = 'extend', metavar = '', help ='column(s) to scale') parser.add_option('-f','--factor', @@ -32,61 +31,21 @@ parser.add_option('-f','--factor', help = 'factor(s) per column') parser.set_defaults(label = [], - ) + factor = []) (options,filenames) = parser.parse_args() - -if len(options.label) != len(options.factor): - parser.error('number of column labels and factors do not match.') - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if len(options.labels) != len(options.factor): + parser.error('number of column labels and factors do not match.') + for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for i,label in enumerate(options.labels): + table.set(label, + table.get(label)*float(options.factor[i]), + scriptID+' '+' '.join(sys.argv[1:])) - table.head_read() - - errors = [] - remarks = [] - columns = [] - dims = [] - factors = [] - - for what,factor in zip(options.label,options.factor): - col = table.label_index(what) - if col < 0: remarks.append('column {} not found...'.format(what,type)) - else: - columns.append(col) - factors.append(float(factor)) - dims.append(table.label_dimension(what)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - for col,dim,factor in zip(columns,dims,factors): # loop over items - table.data[col:col+dim] = factor * np.array(table.data[col:col+dim],'d') - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/shiftData.py b/processing/post/shiftData.py index 69a9696fa..57b20fbd0 100755 --- a/processing/post/shiftData.py +++ b/processing/post/shiftData.py @@ -2,10 +2,9 @@ import os import sys +from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -23,7 +22,7 @@ Uniformly shift column values by given offset. """, version = scriptID) parser.add_option('-l','--label', - dest = 'label', + dest = 'labels', action = 'extend', metavar = '', help ='column(s) to shift') parser.add_option('-o','--offset', @@ -32,61 +31,21 @@ parser.add_option('-o','--offset', help = 'offset(s) per column') parser.set_defaults(label = [], - ) + offset = []) (options,filenames) = parser.parse_args() - -if len(options.label) != len(options.offset): - parser.error('number of column labels and offsets do not match.') - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if len(options.labels) != len(options.offset): + parser.error('number of column labels and offsets do not match.') + for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for i,label in enumerate(options.labels): + table.set(label, + table.get(label)+float(options.offset[i]), + scriptID+' '+' '.join(sys.argv[1:])) - table.head_read() - - errors = [] - remarks = [] - columns = [] - dims = [] - offsets = [] - - for what,offset in zip(options.label,options.offset): - col = table.label_index(what) - if col < 0: remarks.append('column {} not found...'.format(what,type)) - else: - columns.append(col) - offsets.append(float(offset)) - dims.append(table.label_dimension(what)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - for col,dim,offset in zip(columns,dims,offsets): # loop over items - table.data[col:col+dim] = offset + np.array(table.data[col:col+dim],'d') - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/sortTable.py b/processing/post/sortTable.py index 53a357226..3a3738d18 100755 --- a/processing/post/sortTable.py +++ b/processing/post/sortTable.py @@ -2,10 +2,9 @@ import os import sys +from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -26,7 +25,7 @@ With coordinates in columns "x", "y", and "z"; sorting with x slowest and z fast parser.add_option('-l','--label', - dest = 'keys', + dest = 'labels', action = 'extend', metavar = '', help = 'list of column labels (a,b,c,...)') parser.add_option('-r','--reverse', @@ -38,42 +37,14 @@ parser.set_defaults(reverse = False, ) (options,filenames) = parser.parse_args() - - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if options.labels is None: + parser.error('no labels specified.') for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ assemble header --------------------------------------- + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + table.sort_by(options.labels,not options.reverse) - table.head_read() - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data --------------------------------------- - - table.data_readArray() - - keys = table.labels(raw = True)[::-1] if options.keys is None else options.keys[::-1] # numpy sorts with most significant column as last - - cols = [] - remarks = [] - for i,column in enumerate(table.label_index(keys)): - if column < 0: remarks.append('label "{}" not present...'.format(keys[i])) - else: cols += [table.data[:,column]] - if remarks != []: damask.util.croak(remarks) - - ind = np.lexsort(cols) if cols != [] else np.arange(table.data.shape[0]) - if options.reverse: ind = ind[::-1] - -# ------------------------------------------ output result --------------------------------------- - - table.data = table.data[ind] - table.data_writeArray() - table.close() # close ASCII table + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/pre/abq_addUserOutput.py b/processing/pre/abq_addUserOutput.py deleted file mode 100755 index 6df80ee82..000000000 --- a/processing/pre/abq_addUserOutput.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import sys,os,re -from optparse import OptionParser -import damask - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -# ----------------------------- -def ParseOutputFormat(filename,what,me): - format = {'outputs':{},'specials':{'brothers':[]}} - - outputmetafile = filename+'.output'+what - try: - myFile = open(outputmetafile) - except: - print('Could not open file %s'%outputmetafile) - raise - else: - content = myFile.readlines() - myFile.close() - - tag = '' - tagID = 0 - for line in content: - if re.match("\s*$",line) or re.match("#",line): # skip blank lines and comments - continue - m = re.match("\[(.+)\]",line) # look for block indicator - if m: # next section - tag = m.group(1) - tagID += 1 - format['specials']['brothers'].append(tag) - if tag == me or (me.isdigit() and tagID == int(me)): - format['specials']['_id'] = tagID - format['outputs'] = [] - tag = me - else: # data from section - if tag == me: - (output,length) = line.split() - output.lower() - if length.isdigit(): - length = int(length) - if re.match("\((.+)\)",output): # special data, (e.g. (Ngrains) - format['specials'][output] = length - elif length > 0: - format['outputs'].append([output,length]) - return format - - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog [option(s)] Abaqus.Inputfile(s)', description = """ -Transfer the output variables requested in the material.config to -properly labelled user-defined variables within the Abaqus input file (*.inp). - -Requires the files -.output -that are written during the first run of the model. - -Specify which user block format you want to apply by stating the homogenization, crystallite, and phase identifiers. -Or have an existing set of user variables copied over from another *.inp file. - -""", version = scriptID) - -parser.add_option('-m', dest='number', type='int', metavar = 'int', - help='maximum requested User Defined Variable [%default]') -parser.add_option('--homogenization', dest='homog', metavar = 'string', - help='homogenization name or index [%default]') -parser.add_option('--crystallite', dest='cryst', metavar = 'string', - help='crystallite identifier name or index [%default]') -parser.add_option('--phase', dest='phase', metavar = 'string', - help='phase identifier name or index [%default]') -parser.add_option('--use', dest='useFile', metavar = 'string', - help='optionally parse output descriptors from '+ - 'outputXXX files of given name') -parser.add_option('--option', dest='damaskOption', metavar = 'string', - help='Add DAMASK option to input file, e.g. "periodic x z"') - -parser.set_defaults(number = 0, - homog = '1', - cryst = '1', - phase = '1') - -(options, files) = parser.parse_args() - -if not files: - parser.error('no file(s) specified.') - -me = { 'Homogenization': options.homog, - 'Crystallite': options.cryst, - 'Constitutive': options.phase, - } - - -for myFile in files: - damask.util.report(scriptName,myFile) - if options.useFile is not None: - formatFile = os.path.splitext(options.useFile)[0] - else: - formatFile = os.path.splitext(myFile)[0] - myFile = os.path.splitext(myFile)[0]+'.inp' - if not os.path.lexists(myFile): - print('{} not found'.format(myFile)) - continue - - print('Scanning format files of: {}'.format(formatFile)) - - if options.number < 1: - outputFormat = {} - - for what in me: - outputFormat[what] = ParseOutputFormat(formatFile,what,me[what]) - if '_id' not in outputFormat[what]['specials']: - print("'{}' not found in <{}>".format(me[what],what)) - print('\n'.join(map(lambda x:' '+x,outputFormat[what]['specials']['brothers']))) - sys.exit(1) - - UserVars = ['HomogenizationCount'] - for var in outputFormat['Homogenization']['outputs']: - if var[1] > 1: - UserVars += ['%i_%s'%(i+1,var[0]) for i in range(var[1])] - else: - UserVars += ['%s'%(var[0]) for i in range(var[1])] - - UserVars += ['GrainCount'] - - for grain in range(outputFormat['Homogenization']['specials']['(ngrains)']): - UserVars += ['%i_CrystalliteCount'%(grain+1)] - for var in outputFormat['Crystallite']['outputs']: - if var[1] > 1: - UserVars += ['%i_%i_%s'%(grain+1,i+1,var[0]) for i in range(var[1])] - else: - UserVars += ['%i_%s'%(grain+1,var[0]) for i in range(var[1])] - - UserVars += ['%i_ConstitutiveCount'%(grain+1)] - for var in outputFormat['Constitutive']['outputs']: - if var[1] > 1: - UserVars += ['%i_%i_%s'%(grain+1,i+1,var[0]) for i in range(var[1])] - else: - UserVars += ['%i_%s'%(grain+1,var[0]) for i in range(var[1])] - -# Now change *.inp file(s) - print('Adding labels to: {}'.format(myFile)) - inFile = open(myFile) - input = inFile.readlines() - inFile.close() - output = open(myFile,'w') - thisSection = '' - if options.damaskOption is not None: - output.write('$damask {0}\n'.format(options.damaskOption)) - for line in input: - #Abaqus keyword line begins with: *keyword, argument1, ... - m = re.match('([*]\w+)\s',line) - if m: - lastSection = thisSection - thisSection = m.group(1) - if (lastSection.upper() == '*DEPVAR' and thisSection.upper() == '*USER'): # Abaqus keyword can be upper or lower case - if options.number > 0: - output.write('{}\n'.format(options.number)) # Abaqus needs total number of SDVs in the line after *Depvar keyword - else: - output.write('{}\n'.format(len(UserVars))) - - for i in range(len(UserVars)): - output.write('%i,"%i%s","%i%s"\n'%(i+1,0,UserVars[i],0,UserVars[i])) #index,output variable key,output variable description - if (thisSection.upper() != '*DEPVAR' or not re.match('\s*\d',line)): - output.write(line) - output.close() diff --git a/processing/pre/geom_addPrimitive.py b/processing/pre/geom_addPrimitive.py index 3e147e24d..f33ba27b1 100755 --- a/processing/pre/geom_addPrimitive.py +++ b/processing/pre/geom_addPrimitive.py @@ -132,7 +132,4 @@ for name in filenames: damask.util.croak(geom.update(np.where(mask,geom.microstructure,fill))) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_canvas.py b/processing/pre/geom_canvas.py index a44065dd2..edd5fe622 100755 --- a/processing/pre/geom_canvas.py +++ b/processing/pre/geom_canvas.py @@ -61,7 +61,7 @@ for name in filenames: canvas = np.full(new,options.fill if options.fill is not None else np.nanmax(geom.microstructure)+1,geom.microstructure.dtype) - l = np.clip( offset, 0,np.minimum(old +offset,new)) + l = np.clip( offset, 0,np.minimum(old +offset,new)) # noqa r = np.clip( offset+old,0,np.minimum(old*2+offset,new)) L = np.clip(-offset, 0,np.minimum(new -offset,old)) R = np.clip(-offset+new,0,np.minimum(new*2-offset,old)) @@ -71,7 +71,4 @@ for name in filenames: damask.util.croak(geom.update(canvas,origin=origin+offset*size/old,rescale=True)) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_clean.py b/processing/pre/geom_clean.py index aeafe4f09..8883c1b2a 100755 --- a/processing/pre/geom_clean.py +++ b/processing/pre/geom_clean.py @@ -5,9 +5,6 @@ import sys from io import StringIO from optparse import OptionParser -from scipy import ndimage -import numpy as np - import damask @@ -15,11 +12,6 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -def mostFrequent(arr): - unique, inverse = np.unique(arr, return_inverse=True) - return unique[np.argmax(np.bincount(inverse))] - - #-------------------------------------------------------------------------------------------------- # MAIN #-------------------------------------------------------------------------------------------------- @@ -45,13 +37,6 @@ for name in filenames: damask.util.report(scriptName,name) geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) - - damask.util.croak(geom.update(ndimage.filters.generic_filter( - geom.microstructure,mostFrequent, - size=(options.stencil,)*3).astype(geom.microstructure.dtype))) + damask.util.croak(geom.clean(options.stencil)) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_fromDREAM3D.py b/processing/pre/geom_fromDREAM3D.py index 5d41e05b9..159793cd8 100755 --- a/processing/pre/geom_fromDREAM3D.py +++ b/processing/pre/geom_fromDREAM3D.py @@ -86,7 +86,7 @@ for name in filenames: * inFile[os.path.join(group_geom,'SPACING')][...] grid = inFile[os.path.join(group_geom,'DIMENSIONS')][...] origin = inFile[os.path.join(group_geom,'ORIGIN')][...] - except: + except KeyError: errors.append('Geometry data ({}) not found'.format(group_geom)) @@ -98,13 +98,13 @@ for name in filenames: try: quats = np.reshape(inFile[dataset][...],(np.product(grid),4)) rot = [damask.Rotation.fromQuaternion(q,True,P=+1) for q in quats] - except: + except KeyError: errors.append('Pointwise orientation (quaternion) data ({}) not readable'.format(dataset)) dataset = os.path.join(group_pointwise,options.phase) try: phase = np.reshape(inFile[dataset][...],(np.product(grid))) - except: + except KeyError: errors.append('Pointwise phase data ({}) not readable'.format(dataset)) microstructure = np.arange(1,np.product(grid)+1,dtype=int).reshape(grid,order='F') @@ -116,7 +116,7 @@ for name in filenames: dataset = os.path.join(group_pointwise,options.microstructure) try: microstructure = np.transpose(inFile[dataset][...].reshape(grid[::-1]),(2,1,0)) # convert from C ordering - except: + except KeyError: errors.append('Link between pointwise and grain average data ({}) not readable'.format(dataset)) group_average = os.path.join(rootDir,options.basegroup,options.average) @@ -124,13 +124,13 @@ for name in filenames: dataset = os.path.join(group_average,options.quaternion) try: rot = [damask.Rotation.fromQuaternion(q,True,P=+1) for q in inFile[dataset][...][1:]] # skip first entry (unindexed) - except: + except KeyError: errors.append('Average orientation data ({}) not readable'.format(dataset)) dataset = os.path.join(group_average,options.phase) try: phase = [i[0] for i in inFile[dataset][...]][1:] # skip first entry (unindexed) - except: + except KeyError: errors.append('Average phase data ({}) not readable'.format(dataset)) if errors != []: @@ -155,4 +155,4 @@ for name in filenames: homogenization=options.homogenization,comments=header) damask.util.croak(geom) - geom.to_file(os.path.splitext(name)[0]+'.geom') + geom.to_file(os.path.splitext(name)[0]+'.geom',pack=False) diff --git a/processing/pre/geom_fromMinimalSurface.py b/processing/pre/geom_fromMinimalSurface.py index ab42ce5af..bb6859b54 100755 --- a/processing/pre/geom_fromMinimalSurface.py +++ b/processing/pre/geom_fromMinimalSurface.py @@ -89,7 +89,4 @@ geom=damask.Geom(microstructure,options.size, comments=[scriptID + ' ' + ' '.join(sys.argv[1:])]) damask.util.croak(geom) -if name is None: - sys.stdout.write(str(geom.show())) -else: - geom.to_file(name) +geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_fromOsteonGeometry.py b/processing/pre/geom_fromOsteonGeometry.py index 146bf216c..499a8867f 100755 --- a/processing/pre/geom_fromOsteonGeometry.py +++ b/processing/pre/geom_fromOsteonGeometry.py @@ -145,7 +145,4 @@ geom = damask.Geom(microstructure.reshape(grid), homogenization=options.homogenization,comments=header) damask.util.croak(geom) -if name is None: - sys.stdout.write(str(geom.show())) -else: - geom.to_file(name) +geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_fromScratch.py b/processing/pre/geom_fromScratch.py index bfb294080..89fd27be5 100755 --- a/processing/pre/geom_fromScratch.py +++ b/processing/pre/geom_fromScratch.py @@ -63,7 +63,4 @@ geom = damask.Geom(microstructure=np.full(options.grid,options.fill,dtype=dtype) comments=scriptID + ' ' + ' '.join(sys.argv[1:])) damask.util.croak(geom) -if name is None: - sys.stdout.write(str(geom.show())) -else: - geom.to_file(name) +geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_fromTable.py b/processing/pre/geom_fromTable.py index aa37451c7..f513c4834 100755 --- a/processing/pre/geom_fromTable.py +++ b/processing/pre/geom_fromTable.py @@ -152,7 +152,4 @@ for name in filenames: homogenization=options.homogenization,comments=header) damask.util.croak(geom) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(os.path.splitext(name)[0]+'.geom') + geom.to_file(sys.stdout if name is None else os.path.splitext(name)[0]+'.geom',pack=False) diff --git a/processing/pre/geom_fromVoronoiTessellation.py b/processing/pre/geom_fromVoronoiTessellation.py index 9d4573c2c..28e215f85 100755 --- a/processing/pre/geom_fromVoronoiTessellation.py +++ b/processing/pre/geom_fromVoronoiTessellation.py @@ -302,7 +302,4 @@ for name in filenames: homogenization=options.homogenization,comments=header) damask.util.croak(geom) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(os.path.splitext(name)[0]+'.geom') + geom.to_file(sys.stdout if name is None else os.path.splitext(name)[0]+'.geom',pack=False) diff --git a/processing/pre/geom_grainGrowth.py b/processing/pre/geom_grainGrowth.py index b31fc13f2..bdf8d8efe 100755 --- a/processing/pre/geom_grainGrowth.py +++ b/processing/pre/geom_grainGrowth.py @@ -172,7 +172,4 @@ for name in filenames: damask.util.croak(geom.update(microstructure[0:grid_original[0],0:grid_original[1],0:grid_original[2]])) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_mirror.py b/processing/pre/geom_mirror.py index 67bd2366f..cca0a4e10 100755 --- a/processing/pre/geom_mirror.py +++ b/processing/pre/geom_mirror.py @@ -5,8 +5,6 @@ import sys from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -38,35 +36,12 @@ parser.set_defaults(reflect = False) (options, filenames) = parser.parse_args() -if options.directions is None: - parser.error('no direction given.') - -if not set(options.directions).issubset(validDirections): - invalidDirections = [str(e) for e in set(options.directions).difference(validDirections)] - parser.error('invalid directions {}. '.format(*invalidDirections)) - -limits = [None,None] if options.reflect else [-2,0] - - if filenames == []: filenames = [None] for name in filenames: damask.util.report(scriptName,name) geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) - - microstructure = geom.get_microstructure() - if 'z' in options.directions: - microstructure = np.concatenate([microstructure,microstructure[:,:,limits[0]:limits[1]:-1]],2) - if 'y' in options.directions: - microstructure = np.concatenate([microstructure,microstructure[:,limits[0]:limits[1]:-1,:]],1) - if 'x' in options.directions: - microstructure = np.concatenate([microstructure,microstructure[limits[0]:limits[1]:-1,:,:]],0) - - damask.util.croak(geom.update(microstructure,rescale=True)) + damask.util.croak(geom.mirror(options.directions,options.reflect)) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_pack.py b/processing/pre/geom_pack.py index 786a40b95..e927c006f 100755 --- a/processing/pre/geom_pack.py +++ b/processing/pre/geom_pack.py @@ -33,42 +33,5 @@ for name in filenames: damask.util.croak(geom) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - - compressType = None - former = start = -1 - reps = 0 - - if name is None: - f = sys.stdout - else: - f= open(name,'w') - - for current in geom.microstructure.flatten('F'): - if abs(current - former) == 1 and (start - current) == reps*(former - current): - compressType = 'to' - reps += 1 - elif current == former and start == former: - compressType = 'of' - reps += 1 - else: - if compressType is None: - f.write('\n'.join(geom.get_header())+'\n') - elif compressType == '.': - f.write('{}\n'.format(former)) - elif compressType == 'to': - f.write('{} to {}\n'.format(start,former)) - elif compressType == 'of': - f.write('{} of {}\n'.format(reps,former)) - - compressType = '.' - start = current - reps = 1 - - former = current - - if compressType == '.': - f.write('{}\n'.format(former)) - elif compressType == 'to': - f.write('{} to {}\n'.format(start,former)) - elif compressType == 'of': - f.write('{} of {}\n'.format(reps,former)) + + geom.to_file(sys.stdout if name is None else name,pack=True) diff --git a/processing/pre/geom_renumber.py b/processing/pre/geom_renumber.py index 2eee189e1..6e51062a5 100755 --- a/processing/pre/geom_renumber.py +++ b/processing/pre/geom_renumber.py @@ -5,8 +5,6 @@ import sys from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -32,15 +30,6 @@ for name in filenames: damask.util.report(scriptName,name) geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) - - renumbered = np.empty(geom.get_grid(),dtype=geom.microstructure.dtype) - for i, oldID in enumerate(np.unique(geom.microstructure)): - renumbered = np.where(geom.microstructure == oldID, i+1, renumbered) - - damask.util.croak(geom.update(renumbered)) + damask.util.croak(geom.renumber()) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_rescale.py b/processing/pre/geom_rescale.py index e84c7597b..b1a15593c 100755 --- a/processing/pre/geom_rescale.py +++ b/processing/pre/geom_rescale.py @@ -2,11 +2,10 @@ import os import sys -import numpy as np - from io import StringIO from optparse import OptionParser -from scipy import ndimage + +import numpy as np import damask @@ -55,20 +54,7 @@ for name in filenames: np.array([o*float(n.lower().replace('x','')) if n.lower().endswith('x') \ else float(n) for o,n in zip(size,options.size)],dtype=float) - damask.util.croak(geom.update(microstructure = - ndimage.interpolation.zoom( - geom.microstructure, - new_grid/grid, - output=geom.microstructure.dtype, - order=0, - mode='nearest', - prefilter=False, - ) if np.any(new_grid != grid) \ - else None, - size = new_size)) + geom.scale(new_grid) + damask.util.croak(geom.update(microstructure = None,size = new_size)) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_rotate.py b/processing/pre/geom_rotate.py index c2a4af04b..977e00b65 100755 --- a/processing/pre/geom_rotate.py +++ b/processing/pre/geom_rotate.py @@ -95,7 +95,4 @@ for name in filenames: damask.util.croak(geom.update(microstructure,origin=origin-(np.asarray(microstructure.shape)-grid)/2*size/grid,rescale=True)) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_translate.py b/processing/pre/geom_translate.py index 4b91920ae..2d4279821 100755 --- a/processing/pre/geom_translate.py +++ b/processing/pre/geom_translate.py @@ -58,7 +58,4 @@ for name in filenames: damask.util.croak(geom.update(substituted,origin=geom.get_origin()+options.origin)) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_unpack.py b/processing/pre/geom_unpack.py index 2a2d54130..58bd5de87 100755 --- a/processing/pre/geom_unpack.py +++ b/processing/pre/geom_unpack.py @@ -34,7 +34,4 @@ for name in filenames: damask.util.croak(geom) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/geom_vicinityOffset.py b/processing/pre/geom_vicinityOffset.py index 3a4853121..e30779d31 100755 --- a/processing/pre/geom_vicinityOffset.py +++ b/processing/pre/geom_vicinityOffset.py @@ -82,7 +82,4 @@ for name in filenames: geom.microstructure + offset,geom.microstructure))) geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:])) - if name is None: - sys.stdout.write(str(geom.show())) - else: - geom.to_file(name) + geom.to_file(sys.stdout if name is None else name,pack=False) diff --git a/processing/pre/marc_addUserOutput.py b/processing/pre/marc_addUserOutput.py deleted file mode 100755 index 94b6c3503..000000000 --- a/processing/pre/marc_addUserOutput.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 no BOM -*- - -import sys,os,re -from optparse import OptionParser -import damask - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -# ----------------------------- -def ParseOutputFormat(filename,what,me): - format = {'outputs':{},'specials':{'brothers':[]}} - - outputmetafile = filename+'.output'+what - try: - myFile = open(outputmetafile) - except: - print('Could not open file %s'%outputmetafile) - raise - else: - content = myFile.readlines() - myFile.close() - - tag = '' - tagID = 0 - for line in content: - if re.match("\s*$",line) or re.match("#",line): # skip blank lines and comments - continue - m = re.match("\[(.+)\]",line) # look for block indicator - if m: # next section - tag = m.group(1) - tagID += 1 - format['specials']['brothers'].append(tag) - if tag == me or (me.isdigit() and tagID == int(me)): - format['specials']['_id'] = tagID - format['outputs'] = [] - tag = me - else: # data from section - if tag == me: - (output,length) = line.split() - output.lower() - if length.isdigit(): - length = int(length) - if re.match("\((.+)\)",output): # special data, (e.g. (Ngrains) - format['specials'][output] = length - elif length > 0: - format['outputs'].append([output,length]) - return format - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog [option(s)] Marc.Inputfile(s)', description = """ -Transfer the output variables requested in the material.config to -properly labelled user-defined variables within the Marc input file (*.dat). - -Requires the files -.output -that are written during the first run of the model. - -Specify which user block format you want to apply by stating the homogenization, crystallite, and phase identifiers. -Or have an existing set of user variables copied over from another *.dat file. - -""", version = scriptID) - -parser.add_option('-m', dest='number', type='int', metavar = 'int', - help='maximum requested User Defined Variable [%default]') -parser.add_option('--homogenization', dest='homog', metavar = 'string', - help='homogenization name or index [%default]') -parser.add_option('--crystallite', dest='cryst', metavar = 'string', - help='crystallite identifier name or index [%default]') -parser.add_option('--phase', dest='phase', metavar = 'string', - help='phase identifier name or index [%default]') -parser.add_option('--use', dest='useFile', metavar = 'string', - help='optionally parse output descriptors from '+ - 'outputXXX files of given name') -parser.add_option('--option', dest='damaskOption', metavar = 'string', - help='Add DAMASK option to input file, e.g. "periodic x z"') - -parser.set_defaults(number = 0, - homog = '1', - cryst = '1', - phase = '1') - -(options, files) = parser.parse_args() - -if not files: - parser.error('no file(s) specified.') - -me = { 'Homogenization': options.homog, - 'Crystallite': options.cryst, - 'Constitutive': options.phase, - } - - -for myFile in files: - damask.util.report(scriptName,myFile) - if options.useFile is not None: - formatFile = os.path.splitext(options.useFile)[0] - else: - formatFile = os.path.splitext(myFile)[0] - myFile = os.path.splitext(myFile)[0]+'.dat' - if not os.path.lexists(myFile): - print('{} not found'.format(myFile)) - continue - - print('Scanning format files of: {}'.format(formatFile)) - - if options.number < 1: - outputFormat = {} - - for what in me: - outputFormat[what] = ParseOutputFormat(formatFile,what,me[what]) - if '_id' not in outputFormat[what]['specials']: - print("'{}' not found in <{}>".format(me[what],what)) - print('\n'.join(map(lambda x:' '+x,outputFormat[what]['specials']['brothers']))) - sys.exit(1) - - UserVars = ['HomogenizationCount'] - for var in outputFormat['Homogenization']['outputs']: - if var[1] > 1: - UserVars += ['%i_%s'%(i+1,var[0]) for i in range(var[1])] - else: - UserVars += ['%s'%(var[0]) for i in range(var[1])] - - UserVars += ['GrainCount'] - - for grain in range(outputFormat['Homogenization']['specials']['(ngrains)']): - UserVars += ['%i_CrystalliteCount'%(grain+1)] - for var in outputFormat['Crystallite']['outputs']: - if var[1] > 1: - UserVars += ['%i_%i_%s'%(grain+1,i+1,var[0]) for i in range(var[1])] - else: - UserVars += ['%i_%s'%(grain+1,var[0]) for i in range(var[1])] - - UserVars += ['%i_ConstitutiveCount'%(grain+1)] - for var in outputFormat['Constitutive']['outputs']: - if var[1] > 1: - UserVars += ['%i_%i_%s'%(grain+1,i+1,var[0]) for i in range(var[1])] - else: - UserVars += ['%i_%s'%(grain+1,var[0]) for i in range(var[1])] - -# Now change *.dat file(s) - print('Adding labels to: {}'.format(myFile)) - inFile = open(myFile) - input = inFile.readlines() - inFile.close() - output = open(myFile,'w') - thisSection = '' - if options.damaskOption is not None: - output.write('$damask {0}\n'.format(options.damaskOption)) - for line in input: - m = re.match('(\w+)\s',line) - if m: - lastSection = thisSection - thisSection = m.group(1) - if (lastSection == 'post' and thisSection == 'parameters'): - if options.number > 0: - for i in range(options.number): - output.write('%10i%10i\n'%(-i-1,0)) - else: - for i in range(len(UserVars)): - output.write('%10i%10i%s\n'%(-i-1,0,UserVars[i])) - if (thisSection != 'post' or not re.match('\s*\-',line)): - output.write(line) - output.close() diff --git a/python/damask/__init__.py b/python/damask/__init__.py index ed6747a93..2cd26cf1c 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -2,20 +2,25 @@ import os with open(os.path.join(os.path.dirname(__file__),'VERSION')) as f: - version = f.readline()[1:-1] + version = f.readline()[1:-1] name = 'damask' +# classes from .environment import Environment # noqa from .asciitable import ASCIItable # noqa +from .table import Table # noqa from .config import Material # noqa from .colormaps import Colormap, Color # noqa from .orientation import Symmetry, Lattice, Rotation, Orientation # noqa from .dadf5 import DADF5 # noqa -#from .block import Block # only one class from .geom import Geom # noqa from .solver import Solver # noqa from .test import Test # noqa from .util import extendableOption # noqa + +# functions in modules +from . import mechanics # noqa + diff --git a/python/damask/asciitable.py b/python/damask/asciitable.py index 59e285d6a..13ca0116b 100644 --- a/python/damask/asciitable.py +++ b/python/damask/asciitable.py @@ -2,7 +2,7 @@ import os import sys import re import shlex -from collections import Iterable +from collections.abc import Iterable import numpy as np @@ -15,7 +15,7 @@ except NameError: # ------------------------------------------------------------------ class ASCIItable(): - """Read and write to ASCII tables""" + """Read and write to ASCII tables.""" tmpext = '_tmp' # filename extension for in-place access @@ -27,6 +27,7 @@ class ASCIItable(): labeled = True, # assume table has labels readonly = False, # no reading from file ): + """Read and write to ASCII tables.""" self.__IO__ = {'output': [], 'buffered': buffered, 'labeled': labeled, # header contains labels @@ -72,7 +73,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def _removeCRLF(self, string): - """Delete any carriage return and line feed from string""" + """Delete any carriage return and line feed from string.""" try: return string.replace('\n','').replace('\r','') except AttributeError: @@ -82,7 +83,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def _quote(self, what): - """Quote empty or white space-containing output""" + """Quote empty or white space-containing output.""" return '{quote}{content}{quote}'.format( quote = ('"' if str(what)=='' or re.search(r"\s",str(what)) else ''), content = what) @@ -103,7 +104,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def output_write(self, what): - """Aggregate a single row (string) or list of (possibly containing further lists of) rows into output""" + """Aggregate a single row (string) or list of (possibly containing further lists of) rows into output.""" if isinstance(what, (str, unicode)): self.__IO__['output'] += [what] else: @@ -143,7 +144,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_read(self): """ - Get column labels + Get column labels. by either reading the first row or, if keyword "head[*]" is present, the last line of the header @@ -154,7 +155,7 @@ class ASCIItable(): pass firstline = self.__IO__['in'].readline().strip() - m = re.search('(\d+)\s+head', firstline.lower()) # search for "head" keyword + m = re.search(r'(\d+)\s+head', firstline.lower()) # search for "head" keyword if m: # proper ASCIItable format @@ -194,7 +195,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_write(self, header = True): - """Write current header information (info + labels)""" + """Write current header information (info + labels).""" head = ['{}\theader'.format(len(self.info)+self.__IO__['labeled'])] if header else [] head.append(self.info) if self.__IO__['labeled']: @@ -205,7 +206,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_getGeom(self): - """Interpret geom header""" + """Interpret geom header.""" identifiers = { 'grid': ['a','b','c'], 'size': ['x','y','z'], @@ -247,7 +248,7 @@ class ASCIItable(): def labels_append(self, what, reset = False): - """Add item or list to existing set of labels (and switch on labeling)""" + """Add item or list to existing set of labels (and switch on labeling).""" if isinstance(what, (str, unicode)): self.tags += [self._removeCRLF(what)] else: @@ -261,7 +262,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def labels_clear(self): - """Delete existing labels and switch to no labeling""" + """Delete existing labels and switch to no labeling.""" self.tags = [] self.__IO__['labeled'] = False @@ -392,7 +393,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def info_append(self, what): - """Add item or list to existing set of infos""" + """Add item or list to existing set of infos.""" if isinstance(what, (str, unicode)): self.info += [self._removeCRLF(what)] else: @@ -403,7 +404,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def info_clear(self): - """Delete any info block""" + """Delete any info block.""" self.info = [] # ------------------------------------------------------------------ @@ -416,7 +417,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_skipLines(self, count): - """Wind forward by count number of lines""" + """Wind forward by count number of lines.""" for i in range(count): alive = self.data_read() @@ -426,7 +427,7 @@ class ASCIItable(): def data_read(self, advance = True, respectLabels = True): - """Read next line (possibly buffered) and parse it into data array""" + """Read next line (possibly buffered) and parse it into data array.""" self.line = self.__IO__['readBuffer'].pop(0) if len(self.__IO__['readBuffer']) > 0 \ else self.__IO__['in'].readline().strip() # take buffered content or get next data row from file @@ -446,9 +447,11 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_readArray(self, labels = []): - """Read whole data of all (given) labels as numpy array""" - try: self.data_rewind() # try to wind back to start of data - except: pass # assume/hope we are at data start already... + """Read whole data of all (given) labels as numpy array.""" + try: + self.data_rewind() # try to wind back to start of data + except IOError: + pass # assume/hope we are at data start already... if labels is None or labels == []: use = None # use all columns (and keep labels intact) @@ -480,7 +483,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_write(self, delimiter = '\t'): - """Write current data array and report alive output back""" + """Write current data array and report alive output back.""" if len(self.data) == 0: return True if isinstance(self.data[0],list): @@ -492,16 +495,16 @@ class ASCIItable(): def data_writeArray(self, fmt = None, delimiter = '\t'): - """Write whole numpy array data""" + """Write whole numpy array data.""" for row in self.data: try: output = [fmt % value for value in row] if fmt else list(map(repr,row)) - except: + except Exception: output = [fmt % row] if fmt else [repr(row)] try: self.__IO__['out'].write(delimiter.join(output) + '\n') - except: + except Exception: pass # ------------------------------------------------------------------ @@ -545,7 +548,7 @@ class ASCIItable(): grid, type = 'i', strict = False): - """Read microstructure data (from .geom format)""" + """Read microstructure data (from .geom format).""" def datatype(item): return int(item) if type.lower() == 'i' else float(item) diff --git a/python/damask/dadf5.py b/python/damask/dadf5.py index 1d09847b1..beced188d 100644 --- a/python/damask/dadf5.py +++ b/python/damask/dadf5.py @@ -7,6 +7,7 @@ import numpy as np from . import util from . import version +from . import mechanics # ------------------------------------------------------------------ class DADF5(): @@ -17,19 +18,26 @@ class DADF5(): """ # ------------------------------------------------------------------ - def __init__(self,filename): + def __init__(self,fname): """ Opens an existing DADF5 file. Parameters ---------- - filename : str + fname : str name of the DADF5 file to be openend. """ - with h5py.File(filename,'r') as f: + with h5py.File(fname,'r') as f: - if f.attrs['DADF5-major'] != 0 or f.attrs['DADF5-minor'] != 2: + try: + self.version_major = f.attrs['DADF5_version_major'] + self.version_minor = f.attrs['DADF5_version_minor'] + except KeyError: + self.version_major = f.attrs['DADF5-major'] + self.version_minor = f.attrs['DADF5-minor'] + + if self.version_major != 0 or not 2 <= self.version_minor <= 4: raise TypeError('Unsupported DADF5 version {} '.format(f.attrs['DADF5-version'])) self.structured = 'grid' in f['geometry'].attrs.keys() @@ -39,8 +47,9 @@ class DADF5(): self.size = f['geometry'].attrs['size'] r=re.compile('inc[0-9]+') - self.increments = [i for i in f.keys() if r.match(i)] - self.times = [round(f[i].attrs['time/s'],12) for i in self.increments] + increments_unsorted = {int(i[3:]):i for i in f.keys() if r.match(i)} + self.increments = [increments_unsorted[i] for i in sorted(increments_unsorted)] + self.times = [round(f[i].attrs['time/s'],12) for i in self.increments] self.Nmaterialpoints, self.Nconstituents = np.shape(f['mapping/cellResults/constituent']) self.materialpoints = [m.decode() for m in np.unique(f['mapping/cellResults/materialpoint']['Name'])] @@ -49,21 +58,21 @@ class DADF5(): self.con_physics = [] for c in self.constituents: self.con_physics += f['/'.join([self.increments[0],'constituent',c])].keys() - self.con_physics = list(set(self.con_physics)) # make unique + self.con_physics = list(set(self.con_physics)) # make unique self.mat_physics = [] for m in self.materialpoints: self.mat_physics += f['/'.join([self.increments[0],'materialpoint',m])].keys() - self.mat_physics = list(set(self.mat_physics)) # make unique + self.mat_physics = list(set(self.mat_physics)) # make unique self.visible= {'increments': self.increments, 'constituents': self.constituents, 'materialpoints': self.materialpoints, - 'constituent': range(self.Nconstituents), # ToDo: stupid naming + 'constituent': range(self.Nconstituents), # ToDo: stupid naming 'con_physics': self.con_physics, 'mat_physics': self.mat_physics} - self.filename = filename + self.fname = fname def __manage_visible(self,datasets,what,action): @@ -90,7 +99,7 @@ class DADF5(): valid = [e for e_ in [glob.fnmatch.filter(getattr(self,what),s) for s in choice] for e in e_] existing = set(self.visible[what]) - + if action == 'set': self.visible[what] = valid elif action == 'add': @@ -102,21 +111,21 @@ class DADF5(): def __time_to_inc(self,start,end): selected = [] for i,time in enumerate(self.times): - if start <= time < end: + if start <= time <= end: selected.append(self.increments[i]) return selected def set_by_time(self,start,end): """ - Sets active time increments based on start and end time. + Set active increments based on start and end time. Parameters ---------- start : float start time (included) end : float - end time (exclcuded) + end time (included) """ self.__manage_visible(self.__time_to_inc(start,end),'increments','set') @@ -124,14 +133,14 @@ class DADF5(): def add_by_time(self,start,end): """ - Adds to active time increments based on start and end time. + Add to active increments based on start and end time. Parameters ---------- start : float start time (included) end : float - end time (exclcuded) + end time (included) """ self.__manage_visible(self.__time_to_inc(start,end),'increments','add') @@ -139,22 +148,76 @@ class DADF5(): def del_by_time(self,start,end): """ - Delets from active time increments based on start and end time. + Delete from active increments based on start and end time. Parameters ---------- start : float start time (included) end : float - end time (exclcuded) + end time (included) """ self.__manage_visible(self.__time_to_inc(start,end),'increments','del') + + + def set_by_increment(self,start,end): + """ + Set active time increments based on start and end increment. + + Parameters + ---------- + start : int + start increment (included) + end : int + end increment (included) + + """ + if self.version_minor >= 4: + self.__manage_visible([ 'inc{}'.format(i) for i in range(start,end+1)],'increments','set') + else: + self.__manage_visible(['inc{:05d}'.format(i) for i in range(start,end+1)],'increments','set') + + + def add_by_increment(self,start,end): + """ + Add to active time increments based on start and end increment. + + Parameters + ---------- + start : int + start increment (included) + end : int + end increment (included) + + """ + if self.version_minor >= 4: + self.__manage_visible([ 'inc{}'.format(i) for i in range(start,end+1)],'increments','add') + else: + self.__manage_visible(['inc{:05d}'.format(i) for i in range(start,end+1)],'increments','add') + + + def del_by_increment(self,start,end): + """ + Delet from active time increments based on start and end increment. + + Parameters + ---------- + start : int + start increment (included) + end : int + end increment (included) + + """ + if self.version_minor >= 4: + self.__manage_visible([ 'inc{}'.format(i) for i in range(start,end+1)],'increments','del') + else: + self.__manage_visible(['inc{:05d}'.format(i) for i in range(start,end+1)],'increments','del') def iter_visible(self,what): """ - Iterates over visible items by setting each one visible. + Iterate over visible items by setting each one visible. Parameters ---------- @@ -176,7 +239,7 @@ class DADF5(): def set_visible(self,what,datasets): """ - Sets active groups. + Set active groups. Parameters ---------- @@ -192,7 +255,7 @@ class DADF5(): def add_visible(self,what,datasets): """ - Adds to active groups. + Add to active groups. Parameters ---------- @@ -208,7 +271,7 @@ class DADF5(): def del_visible(self,what,datasets): """ - Removes from active groupse. + Delete from active groupse. Parameters ---------- @@ -252,7 +315,7 @@ class DADF5(): groups = [] - with h5py.File(self.filename,'r') as f: + with h5py.File(self.fname,'r') as f: for i in self.iter_visible('increments'): for o,p in zip(['constituents','materialpoints'],['con_physics','mat_physics']): for oo in self.iter_visible(o): @@ -267,11 +330,11 @@ class DADF5(): def list_data(self): - """Gives information on all active datasets in the file.""" + """Return information on all active datasets in the file.""" message = '' - with h5py.File(self.filename,'r') as f: - for i in self.iter_visible('increments'): - message+='\n{}\n'.format(i) + with h5py.File(self.fname,'r') as f: + for s,i in enumerate(self.iter_visible('increments')): + message+='\n{} ({}s)\n'.format(i,self.times[s]) for o,p in zip(['constituents','materialpoints'],['con_physics','mat_physics']): for oo in self.iter_visible(o): message+=' {}\n'.format(oo) @@ -280,17 +343,24 @@ class DADF5(): group = '/'.join([i,o[:-1],oo,pp]) # o[:-1]: plural/singular issue for d in f[group].keys(): try: - message+=' {} ({})\n'.format(d,f['/'.join([group,d])].attrs['Description'].decode()) + dataset = f['/'.join([group,d])] + message+=' {} / ({}): {}\n'.format(d,dataset.attrs['Unit'].decode(),dataset.attrs['Description'].decode()) except KeyError: pass return message def get_dataset_location(self,label): - """Returns the location of all active datasets with given label.""" + """Return the location of all active datasets with given label.""" path = [] - with h5py.File(self.filename,'r') as f: - for i in self.iter_visible('increments'): + with h5py.File(self.fname,'r') as f: + for i in self.iter_visible('increments'): + k = '/'.join([i,'geometry',label]) + try: + f[k] + path.append(k) + except KeyError as e: + print('unable to locate geometry dataset: {}'.format(str(e))) for o,p in zip(['constituents','materialpoints'],['con_physics','mat_physics']): for oo in self.iter_visible(o): for pp in self.iter_visible(p): @@ -299,39 +369,43 @@ class DADF5(): f[k] path.append(k) except KeyError as e: - print('unable to locate constituents dataset: '+ str(e)) + print('unable to locate {} dataset: {}'.format(o,str(e))) return path def get_constituent_ID(self,c=0): """Pointwise constituent ID.""" - with h5py.File(self.filename,'r') as f: + with h5py.File(self.fname,'r') as f: names = f['/mapping/cellResults/constituent']['Name'][:,c].astype('str') return np.array([int(n.split('_')[0]) for n in names.tolist()],dtype=np.int32) def get_crystal_structure(self): # ToDo: extension to multi constituents/phase """Info about the crystal structure.""" - with h5py.File(self.filename,'r') as f: + with h5py.File(self.fname,'r') as f: return f[self.get_dataset_location('orientation')[0]].attrs['Lattice'].astype('str') # np.bytes_ to string - def read_dataset(self,path,c): + def read_dataset(self,path,c=0,plain=False): """ Dataset for all points/cells. - If more than one path is given, the dataset is composed of the individual contributions + If more than one path is given, the dataset is composed of the individual contributions. """ - with h5py.File(self.filename,'r') as f: + with h5py.File(self.fname,'r') as f: shape = (self.Nmaterialpoints,) + np.shape(f[path[0]])[1:] if len(shape) == 1: shape = shape +(1,) dataset = np.full(shape,np.nan,dtype=np.dtype(f[path[0]])) for pa in path: - label = pa.split('/')[2] + label = pa.split('/')[2] + + if (pa.split('/')[1] == 'geometry'): + dataset = np.array(f[pa]) + continue p = np.where(f['mapping/cellResults/constituent'][:,c]['Name'] == str.encode(label))[0] if len(p)>0: - u = (f['mapping/cellResults/constituent'][p,c]['Position']) + u = (f['mapping/cellResults/constituent']['Position'][p,c]) a = np.array(f[pa]) if len(a.shape) == 1: a=a.reshape([a.shape[0],1]) @@ -339,17 +413,20 @@ class DADF5(): p = np.where(f['mapping/cellResults/materialpoint']['Name'] == str.encode(label))[0] if len(p)>0: - u = (f['mapping/cellResults/materialpoint'][p.tolist()]['Position']) + u = (f['mapping/cellResults/materialpoint']['Position'][p.tolist()]) a = np.array(f[pa]) if len(a.shape) == 1: a=a.reshape([a.shape[0],1]) dataset[p,:] = a[u,:] - - return dataset + + if plain and dataset.dtype.names is not None: + return dataset.view(('float64',len(dataset.dtype.names))) + else: + return dataset def cell_coordinates(self): - """Initial coordinates of the cell centers.""" + """Return initial coordinates of the cell centers.""" if self.structured: delta = self.size/self.grid*0.5 z, y, x = np.meshgrid(np.linspace(delta[2],self.size[2]-delta[2],self.grid[2]), @@ -358,76 +435,237 @@ class DADF5(): ) return np.concatenate((x[:,:,:,None],y[:,:,:,None],y[:,:,:,None]),axis = 3).reshape([np.product(self.grid),3]) else: - with h5py.File(self.filename,'r') as f: + with h5py.File(self.fname,'r') as f: return f['geometry/x_c'][()] + + + def add_absolute(self,x): + """ + Add absolute value. + + Parameters + ---------- + x : str + Label of the dataset containing a scalar, vector, or tensor. + + """ + def __add_absolute(x): + + return { + 'data': np.abs(x['data']), + 'label': '|{}|'.format(x['label']), + 'meta': { + 'Unit': x['meta']['Unit'], + 'Description': 'Absolute value of {} ({})'.format(x['label'],x['meta']['Description']), + 'Creator': 'dadf5.py:add_abs v{}'.format(version) + } + } + + requested = [{'label':x,'arg':'x'}] + + self.__add_generic_pointwise(__add_absolute,requested) + + + def add_calculation(self,formula,label,unit='n/a',description=None,vectorized=True): + """ + Add result of a general formula. + + Parameters + ---------- + formula : str + Formula, refer to datasets by ‘#Label#‘. + label : str + Label of the dataset containing the result of the calculation. + unit : str, optional + Physical unit of the result. + description : str, optional + Human readable description of the result. + vectorized : bool, optional + Indicate whether the formula is written in vectorized form. Default is ‘True’. + + """ + if vectorized is not True: + raise NotImplementedError + + def __add_calculation(**kwargs): + + formula = kwargs['formula'] + for d in re.findall(r'#(.*?)#',formula): + formula = formula.replace('#{}#'.format(d),"kwargs['{}']['data']".format(d)) + + return { + 'data': eval(formula), + 'label': kwargs['label'], + 'meta': { + 'Unit': kwargs['unit'], + 'Description': '{} (formula: {})'.format(kwargs['description'],kwargs['formula']), + 'Creator': 'dadf5.py:add_calculation v{}'.format(version) + } + } + + requested = [{'label':d,'arg':d} for d in set(re.findall(r'#(.*?)#',formula))] # datasets used in the formula + pass_through = {'formula':formula,'label':label,'unit':unit,'description':description} + + self.__add_generic_pointwise(__add_calculation,requested,pass_through) def add_Cauchy(self,P='P',F='F'): """ - Adds Cauchy stress calculated from 1st Piola-Kirchhoff stress and deformation gradient. + Add Cauchy stress calculated from 1. Piola-Kirchhoff stress and deformation gradient. - Resulting tensor is symmetrized as the Cauchy stress should be symmetric. + Parameters + ---------- + P : str, optional + Label of the dataset containing the 1. Piola-Kirchhoff stress. Default value is ‘P’. + F : str, optional + Label of the dataset containing the deformation gradient. Default value is ‘F’. + """ - def Cauchy(F,P): - sigma = np.einsum('i,ijk,ilk->ijl',1.0/np.linalg.det(F['data']),P['data'],F['data']) - sigma = (sigma + np.transpose(sigma,(0,2,1)))*0.5 # enforce symmetry - return { - 'data' : sigma, - 'label' : 'sigma', - 'meta' : { - 'Unit' : P['meta']['Unit'], - 'Description' : 'Cauchy stress calculated from {} ({}) '.format(P['label'],P['meta']['Description'])+\ - 'and deformation gradient {} ({})'.format(F['label'],F['meta']['Description']), - 'Creator' : 'dadf5.py:add_Cauchy v{}'.format(version) + def __add_Cauchy(F,P): + + return { + 'data': mechanics.Cauchy(F['data'],P['data']), + 'label': 'sigma', + 'meta': { + 'Unit': P['meta']['Unit'], + 'Description': 'Cauchy stress calculated from {} ({}) '.format(P['label'],P['meta']['Description'])+\ + 'and deformation gradient {} ({})'.format(F['label'],F['meta']['Description']), + 'Creator': 'dadf5.py:add_Cauchy v{}'.format(version) } - } + } requested = [{'label':F,'arg':'F'}, {'label':P,'arg':'P'} ] - self.__add_generic_pointwise(Cauchy,requested) + self.__add_generic_pointwise(__add_Cauchy,requested) - def add_Mises(self,x): - """Adds the equivalent Mises stress or strain of a tensor.""" - def Mises(x): + def add_determinant(self,x): + """ + Add the determinant of a tensor. + + Parameters + ---------- + x : str + Label of the dataset containing a tensor. + + """ + def __add_determinant(x): - if x['meta']['Unit'] == b'Pa': #ToDo: Should we use this? Then add_Cauchy and add_strain_tensors also should perform sanity checks - factor = 3.0/2.0 - t = 'stress' - elif x['meta']['Unit'] == b'1': - factor = 2.0/3.0 - t = 'strain' - else: - print(x['meta']['Unit']) + return { + 'data': np.linalg.det(x['data']), + 'label': 'det({})'.format(x['label']), + 'meta': { + 'Unit': x['meta']['Unit'], + 'Description': 'Determinant of tensor {} ({})'.format(x['label'],x['meta']['Description']), + 'Creator': 'dadf5.py:add_determinant v{}'.format(version) + } + } + + requested = [{'label':x,'arg':'x'}] + + self.__add_generic_pointwise(__add_determinant,requested) + + + def add_deviator(self,x): + """ + Add the deviatoric part of a tensor. + + Parameters + ---------- + x : str + Label of the dataset containing a tensor. + + """ + def __add_deviator(x): + + if not np.all(np.array(x['data'].shape[1:]) == np.array([3,3])): raise ValueError - d = x['data'] - dev = d - np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),[d.shape[0],3,3]),np.trace(d,axis1=1,axis2=2)/3.0) - #dev_sym = (dev + np.einsum('ikj',dev))*0.5 # ToDo: this is not needed (only if the input is not symmetric, but then the whole concept breaks down) - - return { - 'data' : np.sqrt(np.einsum('ijk->i',dev**2)*factor), - 'label' : '{}_vM'.format(x['label']), - 'meta' : { - 'Unit' : x['meta']['Unit'], - 'Description' : 'Mises equivalent {} of {} ({})'.format(t,x['label'],x['meta']['Description']), - 'Creator' : 'dadf5.py:add_Mises_stress v{}'.format(version) + return { + 'data': mechanics.deviatoric_part(x['data']), + 'label': 's_{}'.format(x['label']), + 'meta': { + 'Unit': x['meta']['Unit'], + 'Description': 'Deviator of tensor {} ({})'.format(x['label'],x['meta']['Description']), + 'Creator': 'dadf5.py:add_deviator v{}'.format(version) } } requested = [{'label':x,'arg':'x'}] - self.__add_generic_pointwise(Mises,requested) + self.__add_generic_pointwise(__add_deviator,requested) + + + def add_maximum_shear(self,x): + """ + Add maximum shear components of symmetric tensor. + + Parameters + ---------- + x : str + Label of the dataset containing a symmetric tensor. + + """ + def __add_maximum_shear(x): + + return { + 'data': mechanics.maximum_shear(x['data']), + 'label': 'max_shear({})'.format(x['label']), + 'meta': { + 'Unit': x['meta']['Unit'], + 'Description': 'Maximum shear component of of {} ({})'.format(x['label'],x['meta']['Description']), + 'Creator': 'dadf5.py:add_maximum_shear v{}'.format(version) + } + } + + requested = [{'label':x,'arg':'x'}] + + self.__add_generic_pointwise(__add_maximum_shear,requested) + + + def add_Mises(self,x): + """ + Add the equivalent Mises stress or strain of a symmetric tensor. + + Parameters + ---------- + x : str + Label of the dataset containing a symmetric stress or strain tensor. + + """ + def __add_Mises(x): + + t = 'strain' if x['meta']['Unit'] == '1' else \ + 'stress' + return { + 'data': mechanics.Mises_strain(x['data']) if t=='strain' else mechanics.Mises_stress(x['data']), + 'label': '{}_vM'.format(x['label']), + 'meta': { + 'Unit': x['meta']['Unit'], + 'Description': 'Mises equivalent {} of {} ({})'.format(t,x['label'],x['meta']['Description']), + 'Creator': 'dadf5.py:add_Mises v{}'.format(version) + } + } + + requested = [{'label':x,'arg':'x'}] + + self.__add_generic_pointwise(__add_Mises,requested) def add_norm(self,x,ord=None): """ - Adds norm of vector or tensor. + Add the norm of vector or tensor. - See numpy.linalg.norm manual for details. + Parameters + ---------- + x : str + Label of the dataset containing a vector or tensor. + ord : {non-zero int, inf, -inf, ‘fro’, ‘nuc’}, optional + Order of the norm. inf means numpy’s inf object. For details refer to numpy.linalg.norm. + """ - def norm(x,ord): + def __add_norm(x,ord): o = ord if len(x['data'].shape) == 2: @@ -441,178 +679,112 @@ class DADF5(): else: raise ValueError - return { - 'data' : np.linalg.norm(x['data'],ord=o,axis=axis,keepdims=True), - 'label' : '|{}|_{}'.format(x['label'],o), - 'meta' : { - 'Unit' : x['meta']['Unit'], - 'Description' : '{}-Norm of {} {} ({})'.format(ord,t,x['label'],x['meta']['Description']), - 'Creator' : 'dadf5.py:add_norm v{}'.format(version) + return { + 'data': np.linalg.norm(x['data'],ord=o,axis=axis,keepdims=True), + 'label': '|{}|_{}'.format(x['label'],o), + 'meta': { + 'Unit': x['meta']['Unit'], + 'Description': '{}-Norm of {} {} ({})'.format(ord,t,x['label'],x['meta']['Description']), + 'Creator': 'dadf5.py:add_norm v{}'.format(version) } } requested = [{'label':x,'arg':'x'}] - self.__add_generic_pointwise(norm,requested,{'ord':ord}) + self.__add_generic_pointwise(__add_norm,requested,{'ord':ord}) - def add_absolute(self,x): - """Adds absolute value.""" - def absolute(x): + def add_principal_components(self,x): + """ + Add principal components of symmetric tensor. + + The principal components are sorted in descending order, each repeated according to its multiplicity. + + Parameters + ---------- + x : str + Label of the dataset containing a symmetric tensor. - return { - 'data' : np.abs(x['data']), - 'label' : '|{}|'.format(x['label']), - 'meta' : { - 'Unit' : x['meta']['Unit'], - 'Description' : 'Absolute value of {} ({})'.format(x['label'],x['meta']['Description']), - 'Creator' : 'dadf5.py:add_abs v{}'.format(version) + """ + def __add_principal_components(x): + + return { + 'data': mechanics.principal_components(x['data']), + 'label': 'lambda_{}'.format(x['label']), + 'meta': { + 'Unit': x['meta']['Unit'], + 'Description': 'Pricipal components of {} ({})'.format(x['label'],x['meta']['Description']), + 'Creator': 'dadf5.py:add_principal_components v{}'.format(version) } } requested = [{'label':x,'arg':'x'}] - - self.__add_generic_pointwise(absolute,requested) - - def add_determinant(self,x): - """Adds the determinant component of a tensor.""" - def determinant(x): - - return { - 'data' : np.linalg.det(x['data']), - 'label' : 'det({})'.format(x['label']), - 'meta' : { - 'Unit' : x['meta']['Unit'], - 'Description' : 'Determinant of tensor {} ({})'.format(x['label'],x['meta']['Description']), - 'Creator' : 'dadf5.py:add_determinant v{}'.format(version) - } - } - - requested = [{'label':x,'arg':'x'}] - - self.__add_generic_pointwise(determinant,requested) + self.__add_generic_pointwise(__add_principal_components,requested) def add_spherical(self,x): - """Adds the spherical component of a tensor.""" - def spherical(x): + """ + Add the spherical (hydrostatic) part of a tensor. + + Parameters + ---------- + x : str + Label of the dataset containing a tensor. + + """ + def __add_spherical(x): if not np.all(np.array(x['data'].shape[1:]) == np.array([3,3])): raise ValueError - return { - 'data' : np.trace(x['data'],axis1=1,axis2=2)/3.0, - 'label' : 'sph({})'.format(x['label']), - 'meta' : { - 'Unit' : x['meta']['Unit'], - 'Description' : 'Spherical component of tensor {} ({})'.format(x['label'],x['meta']['Description']), - 'Creator' : 'dadf5.py:add_spherical v{}'.format(version) + return { + 'data': mechanics.spherical_part(x['data']), + 'label': 'p_{}'.format(x['label']), + 'meta': { + 'Unit': x['meta']['Unit'], + 'Description': 'Spherical component of tensor {} ({})'.format(x['label'],x['meta']['Description']), + 'Creator': 'dadf5.py:add_spherical v{}'.format(version) } } requested = [{'label':x,'arg':'x'}] - self.__add_generic_pointwise(spherical,requested) + self.__add_generic_pointwise(__add_spherical,requested) - def add_deviator(self,x): - """Adds the deviator of a tensor.""" - def deviator(x): - d = x['data'] - - if not np.all(np.array(d.shape[1:]) == np.array([3,3])): - raise ValueError - - return { - 'data' : d - np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),[d.shape[0],3,3]),np.trace(d,axis1=1,axis2=2)/3.0), - 'label' : 'dev({})'.format(x['label']), - 'meta' : { - 'Unit' : x['meta']['Unit'], - 'Description' : 'Deviator of tensor {} ({})'.format(x['label'],x['meta']['Description']), - 'Creator' : 'dadf5.py:add_deviator v{}'.format(version) - } - } - - requested = [{'label':x,'arg':'x'}] - - self.__add_generic_pointwise(deviator,requested) - - - def add_calculation(self,formula,label,unit='n/a',description=None,vectorized=True): + def add_strain_tensor(self,F='F',t='U',m=0): """ - General formula. + Add strain tensor calculated from a deformation gradient. - Works currently only for vectorized expressions + For details refer to damask.mechanics.strain_tensor + Parameters + ---------- + F : str, optional + Label of the dataset containing the deformation gradient. Default value is ‘F’. + t : {‘V’, ‘U’}, optional + Type of the polar decomposition, ‘V’ for right stretch tensor and ‘U’ for left stretch tensor. + Defaults value is ‘U’. + m : float, optional + Order of the strain calculation. Default value is ‘0.0’. + """ - if vectorized is not True: - raise NotImplementedError - - def calculation(**kwargs): + def __add_strain_tensor(F,t,m): - formula = kwargs['formula'] - for d in re.findall(r'#(.*?)#',formula): - formula = re.sub('#{}#'.format(d),"kwargs['{}']['data']".format(d),formula) - - return { - 'data' : eval(formula), - 'label' : kwargs['label'], - 'meta' : { - 'Unit' : kwargs['unit'], - 'Description' : '{}'.format(kwargs['description']), - 'Creator' : 'dadf5.py:add_calculation v{}'.format(version) - } - } - - requested = [{'label':d,'arg':d} for d in re.findall(r'#(.*?)#',formula)] # datasets used in the formula - pass_through = {'formula':formula,'label':label,'unit':unit,'description':description} - - self.__add_generic_pointwise(calculation,requested,pass_through) - - - def add_strain_tensor(self,t,ord,defgrad='F'): #ToDo: Use t and ord - """ - Adds the a strain tensor. - - Albrecht Bertram: Elasticity and Plasticity of Large Deformations An Introduction (3rd Edition, 2012), p. 102. - """ - def strain_tensor(defgrad,t,ord): - - operator = { - 'V#ln': lambda V: np.log(V), - 'U#ln': lambda U: np.log(U), - 'V#Biot': lambda V: np.broadcast_to(np.ones(3),[V.shape[0],3]) - 1.0/V, - 'U#Biot': lambda U: U - np.broadcast_to(np.ones(3),[U.shape[0],3]), - 'V#Green':lambda V: np.broadcast_to(np.ones(3),[V.shape[0],3]) - 1.0/V**2, - 'U#Green':lambda U: U**2 - np.broadcast_to(np.ones(3),[U.shape[0],3]), - } - - (U,S,Vh) = np.linalg.svd(defgrad['data']) # singular value decomposition - R_inv = np.transpose(np.matmul(U,Vh),(0,2,1)) # transposed rotation of polar decomposition - U = np.matmul(R_inv,defgrad['data']) # F = RU - (D,V) = np.linalg.eigh((U+np.transpose(U,(0,2,1)))*.5) # eigen decomposition (of symmetric(ed) matrix) - - neg = np.where(D < 0.0) # find negative eigenvalues ... - D[neg[0],neg[1]] = D[neg[0],neg[1]]* -1 # ... flip value ... - V[neg[0],:,neg[1]] = V[neg[0],:,neg[1]]* -1 # ... and vector - - d = operator['V#ln'](D) - a = np.matmul(V,np.einsum('ij,ikj->ijk',d,V)) - - return { - 'data' : a, - 'label' : 'ln(V)({})'.format(defgrad['label']), - 'meta' : { - 'Unit' : defgrad['meta']['Unit'], - 'Description' : 'Strain tensor ln(V){} ({})'.format(defgrad['label'],defgrad['meta']['Description']), - 'Creator' : 'dadf5.py:add_deviator v{}'.format(version) + return { + 'data': mechanics.strain_tensor(F['data'],t,m), + 'label': 'epsilon_{}^{}({})'.format(t,m,F['label']), + 'meta': { + 'Unit': F['meta']['Unit'], + 'Description': 'Strain tensor of {} ({})'.format(F['label'],F['meta']['Description']), + 'Creator': 'dadf5.py:add_strain_tensor v{}'.format(version) } } - requested = [{'label':defgrad,'arg':'defgrad'}] + requested = [{'label':F,'arg':'F'}] - self.__add_generic_pointwise(strain_tensor,requested,{'t':t,'ord':ord}) + self.__add_generic_pointwise(__add_strain_tensor,requested,{'t':t,'m':m}) def __add_generic_pointwise(self,func,datasets_requested,extra_args={}): @@ -621,12 +793,12 @@ class DADF5(): Parameters ---------- - func : function - Function that calculates a new dataset from one or more datasets per HDF5 group. - datasets_requested : list of dictionaries - Details of the datasets to be used: label (in HDF5 file) and arg (argument to which the data is parsed in func). - extra_args : dictionary, optional - Any extra arguments parsed to func. + func : function + Function that calculates a new dataset from one or more datasets per HDF5 group. + datasets_requested : list of dictionaries + Details of the datasets to be used: label (in HDF5 file) and arg (argument to which the data is parsed in func). + extra_args : dictionary, optional + Any extra arguments parsed to func. """ def job(args): @@ -643,12 +815,12 @@ class DADF5(): todo = [] # ToDo: It would be more memory efficient to read only from file when required, i.e. do to it in pool.add_task for group in self.groups_with_datasets([d['label'] for d in datasets_requested]): - with h5py.File(self.filename,'r') as f: + with h5py.File(self.fname,'r') as f: datasets_in = {} for d in datasets_requested: loc = f[group+'/'+d['label']] data = loc[()] - meta = {k:loc.attrs[k] for k in loc.attrs.keys()} + meta = {k:loc.attrs[k].decode() for k in loc.attrs.keys()} datasets_in[d['arg']] = {'data': data, 'meta' : meta, 'label' : d['label']} todo.append({'in':{**datasets_in,**extra_args},'func':func,'group':group,'results':results}) @@ -658,10 +830,10 @@ class DADF5(): N_not_calculated = len(todo) while N_not_calculated > 0: result = results.get() - with h5py.File(self.filename,'a') as f: # write to file + with h5py.File(self.fname,'a') as f: # write to file dataset_out = f[result['group']].create_dataset(result['label'],data=result['data']) for k in result['meta'].keys(): - dataset_out.attrs[k] = result['meta'][k] + dataset_out.attrs[k] = result['meta'][k].encode() N_not_calculated-=1 if N_added < len(todo): # add more jobs diff --git a/python/damask/geom.py b/python/damask/geom.py index 176d2bd12..32ea2ed89 100644 --- a/python/damask/geom.py +++ b/python/damask/geom.py @@ -2,6 +2,7 @@ import os from io import StringIO import numpy as np +from scipy import ndimage import vtk from vtk.util import numpy_support @@ -10,380 +11,517 @@ from . import version class Geom(): - """Geometry definition for grid solvers.""" + """Geometry definition for grid solvers.""" - def __init__(self,microstructure,size,origin=[0.0,0.0,0.0],homogenization=1,comments=[]): - """ - New geometry definition from array of microstructures and size. + def __init__(self,microstructure,size,origin=[0.0,0.0,0.0],homogenization=1,comments=[]): + """ + New geometry definition from array of microstructures and size. - Parameters - ---------- - microstructure : numpy.ndarray - microstructure array (3D) - size : list or numpy.ndarray - physical size of the microstructure in meter. - origin : list or numpy.ndarray, optional - physical origin of the microstructure in meter. - homogenization : integer, optional - homogenization index. - comments : list of str, optional - comments lines. + Parameters + ---------- + microstructure : numpy.ndarray + microstructure array (3D) + size : list or numpy.ndarray + physical size of the microstructure in meter. + origin : list or numpy.ndarray, optional + physical origin of the microstructure in meter. + homogenization : integer, optional + homogenization index. + comments : list of str, optional + comments lines. - """ - self.__transforms__ = \ - self.set_microstructure(microstructure) - self.set_size(size) - self.set_origin(origin) - self.set_homogenization(homogenization) - self.set_comments(comments) - - - def __repr__(self): - """Basic information on geometry definition.""" - return util.srepr([ - 'grid a b c: {}'.format(' x '.join(map(str,self.get_grid ()))), - 'size x y z: {}'.format(' x '.join(map(str,self.get_size ()))), - 'origin x y z: {}'.format(' '.join(map(str,self.get_origin()))), - 'homogenization: {}'.format(self.get_homogenization()), - '# microstructures: {}'.format(len(np.unique(self.microstructure))), - 'max microstructure: {}'.format(np.nanmax(self.microstructure)), - ]) - - def update(self,microstructure=None,size=None,origin=None,rescale=False): - """ - Updates microstructure and size. - - Parameters - ---------- - microstructure : numpy.ndarray, optional - microstructure array (3D). - size : list or numpy.ndarray, optional - physical size of the microstructure in meter. - origin : list or numpy.ndarray, optional - physical origin of the microstructure in meter. - rescale : bool, optional - ignore size parameter and rescale according to change of grid points. - - """ - grid_old = self.get_grid() - size_old = self.get_size() - origin_old = self.get_origin() - unique_old = len(np.unique(self.microstructure)) - max_old = np.nanmax(self.microstructure) - - if size is not None and rescale: - raise ValueError('Either set size explicitly or rescale automatically') - - self.set_microstructure(microstructure) - self.set_origin(origin) - - if size is not None: - self.set_size(size) - elif rescale: - self.set_size(self.get_grid()/grid_old*self.size) - - message = ['grid a b c: {}'.format(' x '.join(map(str,grid_old)))] - if np.any(grid_old != self.get_grid()): - message[-1] = util.delete(message[-1]) - message.append(util.emph('grid a b c: {}'.format(' x '.join(map(str,self.get_grid()))))) - - message.append('size x y z: {}'.format(' x '.join(map(str,size_old)))) - if np.any(size_old != self.get_size()): - message[-1] = util.delete(message[-1]) - message.append(util.emph('size x y z: {}'.format(' x '.join(map(str,self.get_size()))))) - - message.append('origin x y z: {}'.format(' '.join(map(str,origin_old)))) - if np.any(origin_old != self.get_origin()): - message[-1] = util.delete(message[-1]) - message.append(util.emph('origin x y z: {}'.format(' '.join(map(str,self.get_origin()))))) - - message.append('homogenization: {}'.format(self.get_homogenization())) - - message.append('# microstructures: {}'.format(unique_old)) - if unique_old != len(np.unique(self.microstructure)): - message[-1] = util.delete(message[-1]) - message.append(util.emph('# microstructures: {}'.format(len(np.unique(self.microstructure))))) - - message.append('max microstructure: {}'.format(max_old)) - if max_old != np.nanmax(self.microstructure): - message[-1] = util.delete(message[-1]) - message.append(util.emph('max microstructure: {}'.format(np.nanmax(self.microstructure)))) - - return util.return_message(message) - - def set_comments(self,comments): - """ - Replaces all existing comments. - - Parameters - ---------- - comments : list of str - new comments. - - """ - self.comments = [] - self.add_comments(comments) - - def add_comments(self,comments): - """ - Appends comments to existing comments. - - Parameters - ---------- - comments : list of str - new comments. - - """ - self.comments += [str(c) for c in comments] if isinstance(comments,list) else [str(comments)] - - def set_microstructure(self,microstructure): - """ - Replaces the existing microstructure representation. - - Parameters - ---------- - microstructure : numpy.ndarray - microstructure array (3D). - - """ - if microstructure is not None: - if len(microstructure.shape) != 3: - raise ValueError('Invalid microstructure shape {}'.format(*microstructure.shape)) - elif microstructure.dtype not in np.sctypes['float'] + np.sctypes['int']: - raise TypeError('Invalid data type {} for microstructure'.format(microstructure.dtype)) - else: - self.microstructure = np.copy(microstructure) - - def set_size(self,size): - """ - Replaces the existing size information. - - Parameters - ---------- - size : list or numpy.ndarray - physical size of the microstructure in meter. - - """ - if size is None: - grid = np.asarray(self.microstructure.shape) - self.size = grid/np.max(grid) - else: - if len(size) != 3 or any(np.array(size)<=0): - raise ValueError('Invalid size {}'.format(*size)) - else: - self.size = np.array(size) - - def set_origin(self,origin): - """ - Replaces the existing origin information. - - Parameters - ---------- - origin : list or numpy.ndarray - physical origin of the microstructure in meter - - """ - if origin is not None: - if len(origin) != 3: - raise ValueError('Invalid origin {}'.format(*origin)) - else: - self.origin = np.array(origin) - - def set_homogenization(self,homogenization): - """ - Replaces the existing homogenization index. - - Parameters - ---------- - homogenization : integer - homogenization index - - """ - if homogenization is not None: - if not isinstance(homogenization,int) or homogenization < 1: - raise TypeError('Invalid homogenization {}'.format(homogenization)) - else: - self.homogenization = homogenization - - - def get_microstructure(self): - """Return the microstructure representation.""" - return np.copy(self.microstructure) - - def get_size(self): - """Return the physical size in meter.""" - return np.copy(self.size) - - def get_origin(self): - """Return the origin in meter.""" - return np.copy(self.origin) - - def get_grid(self): - """Return the grid discretization.""" - return np.array(self.microstructure.shape) - - def get_homogenization(self): - """Return the homogenization index.""" - return self.homogenization - - def get_comments(self): - """Return the comments.""" - return self.comments[:] - - def get_header(self): - """Return the full header (grid, size, origin, homogenization, comments).""" - header = ['{} header'.format(len(self.comments)+4)] + self.comments - header.append('grid a {} b {} c {}'.format(*self.get_grid())) - header.append('size x {} y {} z {}'.format(*self.get_size())) - header.append('origin x {} y {} z {}'.format(*self.get_origin())) - header.append('homogenization {}'.format(self.get_homogenization())) - return header + """ + self.set_microstructure(microstructure) + self.set_size(size) + self.set_origin(origin) + self.set_homogenization(homogenization) + self.set_comments(comments) - @classmethod - def from_file(cls,fname): - """ - Reads a geom file. - Parameters - ---------- - fname : str or file handle - geometry file to read. + def __repr__(self): + """Basic information on geometry definition.""" + return util.srepr([ + 'grid a b c: {}'.format(' x '.join(map(str,self.get_grid ()))), + 'size x y z: {}'.format(' x '.join(map(str,self.get_size ()))), + 'origin x y z: {}'.format(' '.join(map(str,self.get_origin()))), + 'homogenization: {}'.format(self.get_homogenization()), + '# microstructures: {}'.format(len(np.unique(self.microstructure))), + 'max microstructure: {}'.format(np.nanmax(self.microstructure)), + ]) - """ - with (open(fname) if isinstance(fname,str) else fname) as f: - f.seek(0) - header_length,keyword = f.readline().split()[:2] - header_length = int(header_length) - content = f.readlines() + def update(self,microstructure=None,size=None,origin=None,rescale=False): + """ + Updates microstructure and size. - if not keyword.startswith('head') or header_length < 3: - raise TypeError('Header length information missing or invalid') + Parameters + ---------- + microstructure : numpy.ndarray, optional + microstructure array (3D). + size : list or numpy.ndarray, optional + physical size of the microstructure in meter. + origin : list or numpy.ndarray, optional + physical origin of the microstructure in meter. + rescale : bool, optional + ignore size parameter and rescale according to change of grid points. - comments = [] - for i,line in enumerate(content[:header_length]): - items = line.lower().strip().split() - key = items[0] if len(items) > 0 else '' - if key == 'grid': - grid = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']]) - elif key == 'size': - size = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']]) - elif key == 'origin': - origin = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']]) - elif key == 'homogenization': - homogenization = int(items[1]) - else: - comments.append(line.strip()) + """ + grid_old = self.get_grid() + size_old = self.get_size() + origin_old = self.get_origin() + unique_old = len(np.unique(self.microstructure)) + max_old = np.nanmax(self.microstructure) + + if size is not None and rescale: + raise ValueError('Either set size explicitly or rescale automatically') - microstructure = np.empty(grid.prod()) # initialize as flat array - i = 0 - for line in content[header_length:]: - items = line.split() - if len(items) == 3: - if items[1].lower() == 'of': - items = np.ones(int(items[0]))*float(items[2]) - elif items[1].lower() == 'to': - items = np.linspace(int(items[0]),int(items[2]), - abs(int(items[2])-int(items[0]))+1,dtype=float) - else: items = list(map(float,items)) - else: items = list(map(float,items)) + self.set_microstructure(microstructure) + self.set_origin(origin) + + if size is not None: + self.set_size(size) + elif rescale: + self.set_size(self.get_grid()/grid_old*self.size) + + message = ['grid a b c: {}'.format(' x '.join(map(str,grid_old)))] + if np.any(grid_old != self.get_grid()): + message[-1] = util.delete(message[-1]) + message.append(util.emph('grid a b c: {}'.format(' x '.join(map(str,self.get_grid()))))) + + message.append('size x y z: {}'.format(' x '.join(map(str,size_old)))) + if np.any(size_old != self.get_size()): + message[-1] = util.delete(message[-1]) + message.append(util.emph('size x y z: {}'.format(' x '.join(map(str,self.get_size()))))) + + message.append('origin x y z: {}'.format(' '.join(map(str,origin_old)))) + if np.any(origin_old != self.get_origin()): + message[-1] = util.delete(message[-1]) + message.append(util.emph('origin x y z: {}'.format(' '.join(map(str,self.get_origin()))))) + + message.append('homogenization: {}'.format(self.get_homogenization())) + + message.append('# microstructures: {}'.format(unique_old)) + if unique_old != len(np.unique(self.microstructure)): + message[-1] = util.delete(message[-1]) + message.append(util.emph('# microstructures: {}'.format(len(np.unique(self.microstructure))))) + + message.append('max microstructure: {}'.format(max_old)) + if max_old != np.nanmax(self.microstructure): + message[-1] = util.delete(message[-1]) + message.append(util.emph('max microstructure: {}'.format(np.nanmax(self.microstructure)))) + + return util.return_message(message) + + def set_comments(self,comments): + """ + Replaces all existing comments. + + Parameters + ---------- + comments : list of str + new comments. + + """ + self.comments = [] + self.add_comments(comments) - microstructure[i:i+len(items)] = items - i += len(items) + def add_comments(self,comments): + """ + Appends comments to existing comments. + + Parameters + ---------- + comments : list of str + new comments. + + """ + self.comments += [str(c) for c in comments] if isinstance(comments,list) else [str(comments)] + + def set_microstructure(self,microstructure): + """ + Replaces the existing microstructure representation. + + Parameters + ---------- + microstructure : numpy.ndarray + microstructure array (3D). + + """ + if microstructure is not None: + if len(microstructure.shape) != 3: + raise ValueError('Invalid microstructure shape {}'.format(*microstructure.shape)) + elif microstructure.dtype not in np.sctypes['float'] + np.sctypes['int']: + raise TypeError('Invalid data type {} for microstructure'.format(microstructure.dtype)) + else: + self.microstructure = np.copy(microstructure) + + def set_size(self,size): + """ + Replaces the existing size information. + + Parameters + ---------- + size : list or numpy.ndarray + physical size of the microstructure in meter. + + """ + if size is None: + grid = np.asarray(self.microstructure.shape) + self.size = grid/np.max(grid) + else: + if len(size) != 3 or any(np.array(size)<=0): + raise ValueError('Invalid size {}'.format(*size)) + else: + self.size = np.array(size) + + def set_origin(self,origin): + """ + Replaces the existing origin information. + + Parameters + ---------- + origin : list or numpy.ndarray + physical origin of the microstructure in meter + + """ + if origin is not None: + if len(origin) != 3: + raise ValueError('Invalid origin {}'.format(*origin)) + else: + self.origin = np.array(origin) + + def set_homogenization(self,homogenization): + """ + Replaces the existing homogenization index. + + Parameters + ---------- + homogenization : integer + homogenization index + + """ + if homogenization is not None: + if not isinstance(homogenization,int) or homogenization < 1: + raise TypeError('Invalid homogenization {}'.format(homogenization)) + else: + self.homogenization = homogenization + + + def get_microstructure(self): + """Return the microstructure representation.""" + return np.copy(self.microstructure) + + def get_size(self): + """Return the physical size in meter.""" + return np.copy(self.size) + + def get_origin(self): + """Return the origin in meter.""" + return np.copy(self.origin) + + def get_grid(self): + """Return the grid discretization.""" + return np.array(self.microstructure.shape) + + def get_homogenization(self): + """Return the homogenization index.""" + return self.homogenization + + def get_comments(self): + """Return the comments.""" + return self.comments[:] + + def get_header(self): + """Return the full header (grid, size, origin, homogenization, comments).""" + header = ['{} header'.format(len(self.comments)+4)] + self.comments + header.append('grid a {} b {} c {}'.format(*self.get_grid())) + header.append('size x {} y {} z {}'.format(*self.get_size())) + header.append('origin x {} y {} z {}'.format(*self.get_origin())) + header.append('homogenization {}'.format(self.get_homogenization())) + return header + + @staticmethod + def from_file(fname): + """ + Reads a geom file. + + Parameters + ---------- + fname : str or file handle + geometry file to read. + + """ + try: + f = open(fname) + except TypeError: + f = fname + + f.seek(0) + header_length,keyword = f.readline().split()[:2] + header_length = int(header_length) + content = f.readlines() + + if not keyword.startswith('head') or header_length < 3: + raise TypeError('Header length information missing or invalid') + + comments = [] + for i,line in enumerate(content[:header_length]): + items = line.lower().strip().split() + key = items[0] if len(items) > 0 else '' + if key == 'grid': + grid = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']]) + elif key == 'size': + size = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']]) + elif key == 'origin': + origin = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']]) + elif key == 'homogenization': + homogenization = int(items[1]) + else: + comments.append(line.strip()) + + microstructure = np.empty(grid.prod()) # initialize as flat array + i = 0 + for line in content[header_length:]: + items = line.split() + if len(items) == 3: + if items[1].lower() == 'of': + items = np.ones(int(items[0]))*float(items[2]) + elif items[1].lower() == 'to': + items = np.linspace(int(items[0]),int(items[2]), + abs(int(items[2])-int(items[0]))+1,dtype=float) + else: items = list(map(float,items)) + else: items = list(map(float,items)) + microstructure[i:i+len(items)] = items + i += len(items) + + if i != grid.prod(): + raise TypeError('Invalid file: expected {} entries,found {}'.format(grid.prod(),i)) + + microstructure = microstructure.reshape(grid,order='F') + if not np.any(np.mod(microstructure.flatten(),1) != 0.0): # no float present + microstructure = microstructure.astype('int') + + return Geom(microstructure.reshape(grid),size,origin,homogenization,comments) + + + def to_file(self,fname,pack=None): + """ + Writes a geom file. + + Parameters + ---------- + fname : str or file handle + geometry file to write. + pack : bool, optional + compress geometry with 'x of y' and 'a to b'. + + """ + header = self.get_header() + grid = self.get_grid() + + if pack is None: + plain = grid.prod()/np.unique(self.microstructure).size < 250 + else: + plain = not pack + + if plain: + format_string = '%g' if self.microstructure.dtype in np.sctypes['float'] else \ + '%{}i'.format(1+int(np.floor(np.log10(np.nanmax(self.microstructure))))) + np.savetxt(fname, + self.microstructure.reshape([grid[0],np.prod(grid[1:])],order='F').T, + header='\n'.join(header), fmt=format_string, comments='') + else: + try: + f = open(fname,'w') + except TypeError: + f = fname + + compressType = None + former = start = -1 + reps = 0 + for current in self.microstructure.flatten('F'): + if abs(current - former) == 1 and (start - current) == reps*(former - current): + compressType = 'to' + reps += 1 + elif current == former and start == former: + compressType = 'of' + reps += 1 + else: + if compressType is None: + f.write('\n'.join(self.get_header())+'\n') + elif compressType == '.': + f.write('{}\n'.format(former)) + elif compressType == 'to': + f.write('{} to {}\n'.format(start,former)) + elif compressType == 'of': + f.write('{} of {}\n'.format(reps,former)) + + compressType = '.' + start = current + reps = 1 + + former = current + + if compressType == '.': + f.write('{}\n'.format(former)) + elif compressType == 'to': + f.write('{} to {}\n'.format(start,former)) + elif compressType == 'of': + f.write('{} of {}\n'.format(reps,former)) + + + def to_vtk(self,fname=None): + """ + Generates vtk file. + + Parameters + ---------- + fname : str, optional + vtk file to write. If no file is given, a string is returned. + + """ + grid = self.get_grid() + np.ones(3,dtype=int) + size = self.get_size() + origin = self.get_origin() + + coords = [ + np.linspace(0,size[0],grid[0]) + origin[0], + np.linspace(0,size[1],grid[1]) + origin[1], + np.linspace(0,size[2],grid[2]) + origin[2] + ] + + rGrid = vtk.vtkRectilinearGrid() + coordArray = [vtk.vtkDoubleArray(),vtk.vtkDoubleArray(),vtk.vtkDoubleArray()] + + rGrid.SetDimensions(*grid) + for d,coord in enumerate(coords): + for c in coord: + coordArray[d].InsertNextValue(c) + + rGrid.SetXCoordinates(coordArray[0]) + rGrid.SetYCoordinates(coordArray[1]) + rGrid.SetZCoordinates(coordArray[2]) + + ms = numpy_support.numpy_to_vtk(num_array=self.microstructure.flatten(order='F'), + array_type=vtk.VTK_INT if self.microstructure.dtype == int else vtk.VTK_FLOAT) + ms.SetName('microstructure') + rGrid.GetCellData().AddArray(ms) + + + if fname is None: + writer = vtk.vtkDataSetWriter() + writer.SetHeader('damask.Geom '+version) + writer.WriteToOutputStringOn() + else: + writer = vtk.vtkXMLRectilinearGridWriter() + writer.SetCompressorTypeToZLib() + writer.SetDataModeToBinary() + + ext = os.path.splitext(fname)[1] + if ext == '': + name = fname + '.' + writer.GetDefaultFileExtension() + elif ext == writer.GetDefaultFileExtension(): + name = fname + else: + raise ValueError("unknown extension {}".format(ext)) + writer.SetFileName(name) - if i != grid.prod(): - raise TypeError('Invalid file: expected {} entries,found {}'.format(grid.prod(),i)) - - microstructure = microstructure.reshape(grid,order='F') - if not np.any(np.mod(microstructure.flatten(),1) != 0.0): # no float present - microstructure = microstructure.astype('int') - - return cls(microstructure.reshape(grid),size,origin,homogenization,comments) + writer.SetInputData(rGrid) + writer.Write() - def to_file(self,fname): - """ - Writes a geom file. + if fname is None: return writer.GetOutputString() - Parameters - ---------- - fname : str or file handle - geometry file to write. - - """ - header = self.get_header() - grid = self.get_grid() - format_string = '%{}i'.format(1+int(np.floor(np.log10(np.nanmax(self.microstructure))))) if self.microstructure.dtype == int \ - else '%g' - np.savetxt(fname, - self.microstructure.reshape([grid[0],np.prod(grid[1:])],order='F').T, - header='\n'.join(header), fmt=format_string, comments='') + + def show(self): + """Show raw content (as in file).""" + f=StringIO() + self.to_file(f) + f.seek(0) + return ''.join(f.readlines()) - - def to_vtk(self,fname=None): - """ - Generates vtk file. + def mirror(self,directions,reflect=False): + """ + Mirror microstructure along given directions. - Parameters - ---------- - fname : str, optional - vtk file to write. If no file is given, a string is returned. + Parameters + ---------- + directions : iterable containing str + direction(s) along which the microstructure is mirrored. Valid entries are 'x', 'y', 'z'. + reflect : bool, optional + reflect (include) outermost layers. - """ - grid = self.get_grid() + np.ones(3,dtype=int) - size = self.get_size() - origin = self.get_origin() + """ + valid = {'x','y','z'} + if not all(isinstance(d, str) for d in directions): + raise TypeError('Directions are not of type str.') + elif not set(directions).issubset(valid): + raise ValueError('Invalid direction specified {}'.format(*set(directions).difference(valid))) - coords = [ - np.linspace(0,size[0],grid[0]) + origin[0], - np.linspace(0,size[1],grid[1]) + origin[1], - np.linspace(0,size[2],grid[2]) + origin[2] - ] - - rGrid = vtk.vtkRectilinearGrid() - coordArray = [vtk.vtkDoubleArray(),vtk.vtkDoubleArray(),vtk.vtkDoubleArray()] + limits = [None,None] if reflect else [-2,0] + ms = self.get_microstructure() - rGrid.SetDimensions(*grid) - for d,coord in enumerate(coords): - for c in coord: - coordArray[d].InsertNextValue(c) - - rGrid.SetXCoordinates(coordArray[0]) - rGrid.SetYCoordinates(coordArray[1]) - rGrid.SetZCoordinates(coordArray[2]) - - ms = numpy_support.numpy_to_vtk(num_array=self.microstructure.flatten(order='F'), - array_type=vtk.VTK_INT if self.microstructure.dtype == int else vtk.VTK_FLOAT) - ms.SetName('microstructure') - rGrid.GetCellData().AddArray(ms) + if 'z' in directions: + ms = np.concatenate([ms,ms[:,:,limits[0]:limits[1]:-1]],2) + if 'y' in directions: + ms = np.concatenate([ms,ms[:,limits[0]:limits[1]:-1,:]],1) + if 'x' in directions: + ms = np.concatenate([ms,ms[limits[0]:limits[1]:-1,:,:]],0) + + return self.update(ms,rescale=True) + #self.add_comments('tbd') - if fname is None: - writer = vtk.vtkDataSetWriter() - writer.SetHeader('damask.Geom '+version) - writer.WriteToOutputStringOn() - else: - writer = vtk.vtkXMLRectilinearGridWriter() - writer.SetCompressorTypeToZLib() - writer.SetDataModeToBinary() - - ext = os.path.splitext(fname)[1] - if ext == '': - name = fname + '.' + writer.GetDefaultFileExtension() - elif ext == writer.GetDefaultFileExtension(): - name = fname - else: - raise ValueError("unknown extension {}".format(ext)) - writer.SetFileName(name) - - writer.SetInputData(rGrid) - writer.Write() + def scale(self,grid): + """ + Scale microstructure to new grid. - if fname is None: return writer.GetOutputString() + Parameters + ---------- + grid : iterable of int + new grid dimension - - def show(self): - """Show raw content (as in file).""" - f=StringIO() - self.to_file(f) - f.seek(0) - return ''.join(f.readlines()) + """ + return self.update( + ndimage.interpolation.zoom( + self.microstructure, + grid/self.get_grid(), + output=self.microstructure.dtype, + order=0, + mode='nearest', + prefilter=False + ) + ) + #self.add_comments('tbd') + + + def clean(self,stencil=3): + """ + Smooth microstructure by selecting most frequent index within given stencil at each location. + + Parameters + ---------- + stencil : int, optional + size of smoothing stencil. + + """ + def mostFrequent(arr): + unique, inverse = np.unique(arr, return_inverse=True) + return unique[np.argmax(np.bincount(inverse))] + + return self.update(ndimage.filters.generic_filter( + self.microstructure, + mostFrequent, + size=(stencil,)*3 + ).astype(self.microstructure.dtype) + ) + #self.add_comments('tbd') + + + def renumber(self): + """Renumber sorted microstructure indices to 1,...,N.""" + renumbered = np.empty(self.get_grid(),dtype=self.microstructure.dtype) + for i, oldID in enumerate(np.unique(self.microstructure)): + renumbered = np.where(self.microstructure == oldID, i+1, renumbered) + + return self.update(renumbered) + #self.add_comments('tbd') diff --git a/python/damask/mechanics.py b/python/damask/mechanics.py new file mode 100644 index 000000000..5503d7048 --- /dev/null +++ b/python/damask/mechanics.py @@ -0,0 +1,266 @@ +import numpy as np + +def Cauchy(F,P): + """ + Return Cauchy stress calculated from 1. Piola-Kirchhoff stress and deformation gradient. + + Resulting tensor is symmetrized as the Cauchy stress needs to be symmetric. + + Parameters + ---------- + F : numpy.array of shape (:,3,3) or (3,3) + Deformation gradient. + P : numpy.array of shape (:,3,3) or (3,3) + 1. Piola-Kirchhoff stress. + + """ + if np.shape(F) == np.shape(P) == (3,3): + sigma = 1.0/np.linalg.det(F) * np.dot(P,F.T) + else: + sigma = np.einsum('i,ijk,ilk->ijl',1.0/np.linalg.det(F),P,F) + return symmetric(sigma) + + +def PK2(F,P): + """ + Return 2. Piola-Kirchhoff stress calculated from 1. Piola-Kirchhoff stress and deformation gradient. + + Parameters + ---------- + F : numpy.array of shape (:,3,3) or (3,3) + Deformation gradient. + P : numpy.array of shape (:,3,3) or (3,3) + 1. Piola-Kirchhoff stress. + + """ + if np.shape(F) == np.shape(P) == (3,3): + S = np.dot(np.linalg.inv(F),P) + else: + S = np.einsum('ijk,ikl->ijl',np.linalg.inv(F),P) + return S + + +def strain_tensor(F,t,m): + """ + Return strain tensor calculated from deformation gradient. + + For details refer to https://en.wikipedia.org/wiki/Finite_strain_theory and + https://de.wikipedia.org/wiki/Verzerrungstensor + + Parameters + ---------- + F : numpy.array of shape (:,3,3) or (3,3) + Deformation gradient. + t : {‘V’, ‘U’} + Type of the polar decomposition, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. + m : float + Order of the strain. + + """ + F_ = F.reshape((1,3,3)) if F.shape == (3,3) else F + if t == 'U': + B = np.matmul(F_,transpose(F_)) + w,n = np.linalg.eigh(B) + elif t == 'V': + C = np.matmul(transpose(F_),F_) + w,n = np.linalg.eigh(C) + + if m > 0.0: + eps = 1.0/(2.0*abs(m)) * (+ np.matmul(n,np.einsum('ij,ikj->ijk',w**m,n)) + - np.broadcast_to(np.eye(3),[F_.shape[0],3,3])) + elif m < 0.0: + eps = 1.0/(2.0*abs(m)) * (- np.matmul(n,np.einsum('ij,ikj->ijk',w**m,n)) + + np.broadcast_to(np.eye(3),[F_.shape[0],3,3])) + else: + eps = np.matmul(n,np.einsum('ij,ikj->ijk',0.5*np.log(w),n)) + + return eps.reshape((3,3)) if np.shape(F) == (3,3) else \ + eps + + +def deviatoric_part(x): + """ + Return deviatoric part of a tensor. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Tensor of which the deviatoric part is computed. + + """ + return x - np.eye(3)*spherical_part(x) if np.shape(x) == (3,3) else \ + x - np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),[x.shape[0],3,3]),spherical_part(x)) + + +def spherical_part(x): + """ + Return spherical (hydrostatic) part of a tensor. + + A single scalar is returned, i.e. the hydrostatic part is not mapped on the 3rd order identity + matrix. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Tensor of which the hydrostatic part is computed. + + """ + return np.trace(x)/3.0 if np.shape(x) == (3,3) else \ + np.trace(x,axis1=1,axis2=2)/3.0 + + +def Mises_stress(sigma): + """ + Return the Mises equivalent of a stress tensor. + + Parameters + ---------- + sigma : numpy.array of shape (:,3,3) or (3,3) + Symmetric stress tensor of which the von Mises equivalent is computed. + + """ + s = deviatoric_part(sigma) + return np.sqrt(3.0/2.0*(np.sum(s**2.0))) if np.shape(sigma) == (3,3) else \ + np.sqrt(3.0/2.0*np.einsum('ijk->i',s**2.0)) + + +def Mises_strain(epsilon): + """ + Return the Mises equivalent of a strain tensor. + + Parameters + ---------- + epsilon : numpy.array of shape (:,3,3) or (3,3) + Symmetric strain tensor of which the von Mises equivalent is computed. + + """ + s = deviatoric_part(epsilon) + return np.sqrt(2.0/3.0*(np.sum(s**2.0))) if np.shape(epsilon) == (3,3) else \ + np.sqrt(2.0/3.0*np.einsum('ijk->i',s**2.0)) + + +def symmetric(x): + """ + Return the symmetrized tensor. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Tensor of which the symmetrized values are computed. + + """ + return (x+transpose(x))*0.5 + + +def maximum_shear(x): + """ + Return the maximum shear component of a symmetric tensor. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Symmetric tensor of which the maximum shear is computed. + + """ + w = np.linalg.eigvalsh(symmetric(x)) # eigenvalues in ascending order + return (w[2] - w[0])*0.5 if np.shape(x) == (3,3) else \ + (w[:,2] - w[:,0])*0.5 + + +def principal_components(x): + """ + Return the principal components of a symmetric tensor. + + The principal components (eigenvalues) are sorted in descending order, each repeated according to + its multiplicity. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Symmetric tensor of which the principal compontents are computed. + + """ + w = np.linalg.eigvalsh(symmetric(x)) # eigenvalues in ascending order + return w[::-1] if np.shape(x) == (3,3) else \ + w[:,::-1] + + +def transpose(x): + """ + Return the transpose of a tensor. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Tensor of which the transpose is computed. + + """ + return x.T if np.shape(x) == (3,3) else \ + np.transpose(x,(0,2,1)) + + +def rotational_part(x): + """ + Return the rotational part of a tensor. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Tensor of which the rotational part is computed. + + """ + return __polar_decomposition(x,'R')[0] + + +def left_stretch(x): + """ + Return the left stretch of a tensor. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Tensor of which the left stretch is computed. + + """ + return __polar_decomposition(x,'V')[0] + + +def right_stretch(x): + """ + Return the right stretch of a tensor. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Tensor of which the right stretch is computed. + + """ + return __polar_decomposition(x,'U')[0] + + +def __polar_decomposition(x,requested): + """ + Singular value decomposition. + + Parameters + ---------- + x : numpy.array of shape (:,3,3) or (3,3) + Tensor of which the singular values are computed. + requested : iterable of str + Requested outputs: ‘R’ for the rotation tensor, + ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. + + """ + u, s, vh = np.linalg.svd(x) + R = np.dot(u,vh) if np.shape(x) == (3,3) else \ + np.einsum('ijk,ikl->ijl',u,vh) + + output = [] + if 'R' in requested: + output.append(R) + if 'V' in requested: + output.append(np.dot(x,R.T) if np.shape(x) == (3,3) else np.einsum('ijk,ilk->ijl',x,R)) + if 'U' in requested: + output.append(np.dot(R.T,x) if np.shape(x) == (3,3) else np.einsum('ikj,ikl->ijl',R,x)) + + return tuple(output) diff --git a/python/damask/solver/marc.py b/python/damask/solver/marc.py index 5e728545d..971b2226b 100644 --- a/python/damask/solver/marc.py +++ b/python/damask/solver/marc.py @@ -79,9 +79,9 @@ class Marc(Solver): exitnumber = -1 fid_out = open(outFile,'r') for line in fid_out: - if (string.find(line,'tress iteration') is not -1): + if (string.find(line,'tress iteration') != -1): print(line) - elif (string.find(line,'Exit number') is not -1): + elif (string.find(line,'Exit number') != -1): substr = line[string.find(line,'Exit number'):len(line)] exitnumber = int(substr[12:16]) diff --git a/python/damask/table.py b/python/damask/table.py new file mode 100644 index 000000000..6181fdb1f --- /dev/null +++ b/python/damask/table.py @@ -0,0 +1,257 @@ +import re + +import pandas as pd +import numpy as np + +class Table(): + """Store spreadsheet-like data.""" + + def __init__(self,data,shapes,comments=None): + """ + New spreadsheet. + + Parameters + ---------- + data : numpy.ndarray + Data. + shapes : dict with str:tuple pairs + Shapes of the columns. Example 'F':(3,3) for a deformation gradient. + comments : iterable of str, optional + Additional, human-readable information. + + """ + self.comments = [] if comments is None else [c for c in comments] + self.data = pd.DataFrame(data=data) + self.shapes = shapes + self.__label_condensed() + + + def __label_flat(self): + """Label data individually, e.g. v v v ==> 1_v 2_v 3_v.""" + labels = [] + for label,shape in self.shapes.items(): + size = np.prod(shape) + labels += ['{}{}'.format('' if size == 1 else '{}_'.format(i+1),label) for i in range(size)] + self.data.columns = labels + + + def __label_condensed(self): + """Label data condensed, e.g. 1_v 2_v 3_v ==> v v v.""" + labels = [] + for label,shape in self.shapes.items(): + labels += [label] * np.prod(shape) + self.data.columns = labels + + + def __add_comment(self,label,shape,info): + if info is not None: + self.comments.append('{}{}: {}'.format(label, + ' '+str(shape) if np.prod(shape,dtype=int) > 1 else '', + info)) + + + @staticmethod + def from_ASCII(fname): + """ + Create table from ASCII file. + + The first line needs to indicate the number of subsequent header lines as 'n header'. + Vector data column labels are indicated by '1_v, 2_v, ..., n_v'. + Tensor data column labels are indicated by '3x3:1_T, 3x3:2_T, ..., 3x3:9_T'. + + Parameters + ---------- + fname : file, str, or pathlib.Path + Filename or file for reading. + + """ + try: + f = open(fname) + except TypeError: + f = fname + + header,keyword = f.readline().split() + if keyword == 'header': + header = int(header) + else: + raise Exception + comments = [f.readline()[:-1] for i in range(1,header)] + labels = f.readline().split() + + shapes = {} + for label in labels: + tensor_column = re.search(r'[0-9,x]*?:[0-9]*?_',label) + if tensor_column: + my_shape = tensor_column.group().split(':',1)[0].split('x') + shapes[label.split('_',1)[1]] = tuple([int(d) for d in my_shape]) + else: + vector_column = re.match(r'[0-9]*?_',label) + if vector_column: + shapes[label.split('_',1)[1]] = (int(label.split('_',1)[0]),) + else: + shapes[label] = (1,) + + data = pd.read_csv(f,names=list(range(len(labels))),sep=r'\s+').to_numpy() + + return Table(data,shapes,comments) + + @property + def labels(self): + """Return the labels of all columns.""" + return list(self.shapes.keys()) + + + def get(self,label): + """ + Get column data. + + Parameters + ---------- + label : str + Column label. + + """ + if re.match(r'[0-9]*?_',label): + idx,key = label.split('_',1) + data = self.data[key].to_numpy()[:,int(idx)-1].reshape((-1,1)) + else: + data = self.data[label].to_numpy().reshape((-1,)+self.shapes[label]) + + return data.astype(type(data.flatten()[0])) + + + def set(self,label,data,info=None): + """ + Set column data. + + Parameters + ---------- + label : str + Column label. + data : np.ndarray + New data. + info : str, optional + Human-readable information about the new data. + + """ + self.__add_comment(label,data.shape[1:],info) + + if re.match(r'[0-9]*?_',label): + idx,key = label.split('_',1) + iloc = self.data.columns.get_loc(key).tolist().index(True) + int(idx) -1 + self.data.iloc[:,iloc] = data + else: + self.data[label] = data.reshape(self.data[label].shape) + + + def add(self,label,data,info=None): + """ + Add column data. + + Parameters + ---------- + label : str + Column label. + data : np.ndarray + Modified data. + info : str, optional + Human-readable information about the modified data. + + """ + self.__add_comment(label,data.shape[1:],info) + + self.shapes[label] = data.shape[1:] if len(data.shape) > 1 else (1,) + size = np.prod(data.shape[1:],dtype=int) + new = pd.DataFrame(data=data.reshape(-1,size), + columns=[label]*size, + ) + new.index = self.data.index + self.data = pd.concat([self.data,new],axis=1) + + + def delete(self,label): + """ + Delete column data. + + Parameters + ---------- + label : str + Column label. + + """ + self.data.drop(columns=label,inplace=True) + + del self.shapes[label] + + + def rename(self,label_old,label_new,info=None): + """ + Rename column data. + + Parameters + ---------- + label_old : str + Old column label. + label_new : str + New column label. + + """ + self.data.rename(columns={label_old:label_new},inplace=True) + + self.comments.append('{} => {}{}'.format(label_old, + label_new, + '' if info is None else ': {}'.format(info), + )) + + self.shapes[label_new] = self.shapes.pop(label_old) + + + def sort_by(self,labels,ascending=True): + """ + Get column data. + + Parameters + ---------- + label : str or list + Column labels. + ascending : bool or list, optional + Set sort order. + + """ + self.__label_flat() + self.data.sort_values(labels,axis=0,inplace=True,ascending=ascending) + self.__label_condensed() + self.comments.append('sorted by [{}]'.format(', '.join(labels))) + + + def to_ASCII(self,fname): + """ + Store as plain text file. + + Parameters + ---------- + fname : file, str, or pathlib.Path + Filename or file for reading. + + """ + labels = [] + for l in self.shapes: + if(self.shapes[l] == (1,)): + labels.append('{}'.format(l)) + elif(len(self.shapes[l]) == 1): + labels += ['{}_{}'.format(i+1,l) \ + for i in range(self.shapes[l][0])] + else: + labels += ['{}:{}_{}'.format('x'.join([str(d) for d in self.shapes[l]]),i+1,l) \ + for i in range(np.prod(self.shapes[l],dtype=int))] + + header = ['{} header'.format(len(self.comments)+1)] \ + + self.comments \ + + [' '.join(labels)] + + try: + f = open(fname,'w') + except TypeError: + f = fname + for line in header: f.write(line+'\n') + self.data.to_csv(f,sep=' ',index=False,header=False) diff --git a/python/damask/test/test.py b/python/damask/test.py similarity index 97% rename from python/damask/test/test.py rename to python/damask/test.py index e7f2da14a..b1729548d 100644 --- a/python/damask/test/test.py +++ b/python/damask/test.py @@ -1,10 +1,8 @@ -# -*- coding: UTF-8 no BOM -*- - import os,sys,shutil import logging,logging.config import damask import numpy as np -from collections import Iterable +from collections.abc import Iterable from optparse import OptionParser class Test(): @@ -17,7 +15,7 @@ class Test(): variants = [] def __init__(self, **kwargs): - + """New test.""" defaults = {'description': '', 'keep': False, 'accept': False, @@ -120,22 +118,22 @@ class Test(): """Delete directory tree containing current results.""" try: shutil.rmtree(self.dirCurrent()) - except: + except FileNotFoundError: logging.warning('removal of directory "{}" not possible...'.format(self.dirCurrent())) try: os.mkdir(self.dirCurrent()) return True - except: + except FileExistsError: logging.critical('creation of directory "{}" failed.'.format(self.dirCurrent())) return False def prepareAll(self): - """Do all necessary preparations for the whole test""" + """Do all necessary preparations for the whole test.""" return True def prepare(self,variant): - """Do all necessary preparations for the run of each test variant""" + """Do all necessary preparations for the run of each test variant.""" return True @@ -207,9 +205,9 @@ class Test(): for source,target in zip(list(map(mapA,A)),list(map(mapB,B))): try: shutil.copy2(source,target) - except: + except FileNotFoundError: logging.critical('error copying {} to {}'.format(source,target)) - raise + raise FileNotFoundError def copy_Reference2Current(self,sourcefiles=[],targetfiles=[]): @@ -218,9 +216,9 @@ class Test(): for i,f in enumerate(sourcefiles): try: shutil.copy2(self.fileInReference(f),self.fileInCurrent(targetfiles[i])) - except: + except FileNotFoundError: logging.critical('Reference2Current: Unable to copy file "{}"'.format(f)) - raise + raise FileNotFoundError def copy_Base2Current(self,sourceDir,sourcefiles=[],targetfiles=[]): @@ -230,10 +228,10 @@ class Test(): for i,f in enumerate(sourcefiles): try: shutil.copy2(os.path.join(source,f),self.fileInCurrent(targetfiles[i])) - except: + except FileNotFoundError: logging.error(os.path.join(source,f)) logging.critical('Base2Current: Unable to copy file "{}"'.format(f)) - raise + raise FileNotFoundError def copy_Current2Reference(self,sourcefiles=[],targetfiles=[]): @@ -242,9 +240,9 @@ class Test(): for i,f in enumerate(sourcefiles): try: shutil.copy2(self.fileInCurrent(f),self.fileInReference(targetfiles[i])) - except: + except FileNotFoundError: logging.critical('Current2Reference: Unable to copy file "{}"'.format(f)) - raise + raise FileNotFoundError def copy_Proof2Current(self,sourcefiles=[],targetfiles=[]): @@ -253,9 +251,9 @@ class Test(): for i,f in enumerate(sourcefiles): try: shutil.copy2(self.fileInProof(f),self.fileInCurrent(targetfiles[i])) - except: + except FileNotFoundError: logging.critical('Proof2Current: Unable to copy file "{}"'.format(f)) - raise + raise FileNotFoundError def copy_Current2Current(self,sourcefiles=[],targetfiles=[]): @@ -263,9 +261,10 @@ class Test(): for i,f in enumerate(sourcefiles): try: shutil.copy2(self.fileInReference(f),self.fileInCurrent(targetfiles[i])) - except: + except FileNotFoundError: logging.critical('Current2Current: Unable to copy file "{}"'.format(f)) - raise + raise FileNotFoundError + def execute_inCurrentDir(self,cmd,streamIn=None,env=None): @@ -439,7 +438,7 @@ class Test(): stdTol = 1.0e-6, preFilter = 1.0e-9): """ - Calculate statistics of tables + Calculate statistics of tables. threshold can be used to ignore small values (a negative number disables this feature) """ @@ -492,7 +491,7 @@ class Test(): rtol = 1e-5, atol = 1e-8, debug = False): - """Compare multiple tables with np.allclose""" + """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)] diff --git a/python/damask/test/__init__.py b/python/damask/test/__init__.py deleted file mode 100644 index a8d5d5034..000000000 --- a/python/damask/test/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Test functionality.""" - -from .test import Test # noqa diff --git a/python/tests/conftest.py b/python/tests/conftest.py new file mode 100644 index 000000000..a0504c499 --- /dev/null +++ b/python/tests/conftest.py @@ -0,0 +1,21 @@ +import os + +import pytest + +import damask + +def pytest_addoption(parser): + parser.addoption("--update", + action="store_true", + default=False) + +@pytest.fixture +def update(request): + """Store current results as new reference results.""" + return request.config.getoption("--update") + +@pytest.fixture +def reference_dir_base(): + """Directory containing reference results.""" + env = damask.Environment() + return os.path.join(env.rootDir(),'python','tests','reference') diff --git a/python/tests/reference/DADF5/12grains6x7x8.geom b/python/tests/reference/DADF5/12grains6x7x8.geom new file mode 100644 index 000000000..7bb4a3e4d --- /dev/null +++ b/python/tests/reference/DADF5/12grains6x7x8.geom @@ -0,0 +1,125 @@ +68 header +geom_fromVoronoiTessellation 2.0.3-1073-g6f3cb071 + +[Grain1] +(gauss) phi1 358.98 Phi 65.62 phi2 24.48 +[Grain2] +(gauss) phi1 121.05 Phi 176.11 phi2 295.73 +[Grain3] +(gauss) phi1 43.79 Phi 113.76 phi2 345.90 +[Grain4] +(gauss) phi1 265.15 Phi 62.52 phi2 299.71 +[Grain5] +(gauss) phi1 221.23 Phi 26.54 phi2 207.05 +[Grain6] +(gauss) phi1 249.81 Phi 61.47 phi2 152.14 +[Grain7] +(gauss) phi1 332.45 Phi 99.16 phi2 345.34 +[Grain8] +(gauss) phi1 312.27 Phi 118.27 phi2 181.59 +[Grain9] +(gauss) phi1 303.10 Phi 48.21 phi2 358.03 +[Grain10] +(gauss) phi1 338.26 Phi 48.11 phi2 176.78 +[Grain11] +(gauss) phi1 115.17 Phi 56.54 phi2 223.84 +[Grain12] +(gauss) phi1 281.04 Phi 97.48 phi2 27.94 + +[Grain1] +crystallite 1 +(constituent) phase 1 texture 1 fraction 1.0 +[Grain2] +crystallite 1 +(constituent) phase 1 texture 2 fraction 1.0 +[Grain3] +crystallite 1 +(constituent) phase 1 texture 3 fraction 1.0 +[Grain4] +crystallite 1 +(constituent) phase 1 texture 4 fraction 1.0 +[Grain5] +crystallite 1 +(constituent) phase 1 texture 5 fraction 1.0 +[Grain6] +crystallite 1 +(constituent) phase 1 texture 6 fraction 1.0 +[Grain7] +crystallite 1 +(constituent) phase 1 texture 7 fraction 1.0 +[Grain8] +crystallite 1 +(constituent) phase 1 texture 8 fraction 1.0 +[Grain9] +crystallite 1 +(constituent) phase 1 texture 9 fraction 1.0 +[Grain10] +crystallite 1 +(constituent) phase 1 texture 10 fraction 1.0 +[Grain11] +crystallite 1 +(constituent) phase 1 texture 11 fraction 1.0 +[Grain12] +crystallite 1 +(constituent) phase 1 texture 12 fraction 1.0 + +grid a 6 b 7 c 8 +size x 0.75 y 0.875 z 1.0 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 9 3 3 10 9 9 + 9 1 1 1 9 9 + 9 11 1 1 7 9 + 7 11 11 7 7 7 + 7 11 11 7 7 7 +12 3 3 10 7 12 +12 3 3 10 10 12 +12 3 3 1 9 9 + 9 1 1 1 9 9 + 9 1 1 1 7 7 + 7 1 1 7 7 7 +12 12 3 7 7 7 +12 3 3 3 12 12 +12 3 3 3 12 12 +12 3 3 1 1 12 + 9 1 1 1 1 9 + 6 1 1 1 8 8 + 7 6 8 8 8 8 +12 12 8 8 8 12 +12 3 3 3 12 12 +12 3 3 3 12 12 + 5 6 6 6 1 12 + 6 6 6 6 8 8 + 6 6 6 8 8 8 + 8 6 8 8 8 8 +12 5 8 8 8 8 +12 5 5 8 8 12 + 5 5 5 3 12 12 + 5 5 6 6 6 5 + 6 6 6 6 6 6 + 6 6 6 6 8 8 + 4 4 6 8 8 8 + 4 4 2 2 2 8 + 5 5 5 2 2 2 + 5 5 5 5 2 5 + 5 5 5 10 10 5 + 6 6 6 6 10 4 + 4 4 11 11 2 4 + 4 4 11 2 2 4 + 4 4 2 2 2 2 + 5 5 5 2 2 2 + 5 5 5 10 10 5 + 5 5 10 10 10 9 + 4 11 11 11 10 9 + 4 4 11 11 11 4 + 4 4 11 11 2 4 + 4 4 2 2 2 2 + 5 5 2 2 2 2 + 5 5 10 10 10 10 + 9 10 10 10 10 9 + 9 11 11 10 9 9 + 4 11 11 11 9 9 + 4 11 11 11 7 7 + 4 4 11 2 7 7 +12 10 10 10 10 7 + 9 10 10 10 10 9 diff --git a/python/tests/reference/DADF5/12grains6x7x8_tensionY.hdf5 b/python/tests/reference/DADF5/12grains6x7x8_tensionY.hdf5 new file mode 100644 index 000000000..39c17fadb Binary files /dev/null and b/python/tests/reference/DADF5/12grains6x7x8_tensionY.hdf5 differ diff --git a/python/tests/reference/DADF5/material.config b/python/tests/reference/DADF5/material.config new file mode 100644 index 000000000..0b0808a12 --- /dev/null +++ b/python/tests/reference/DADF5/material.config @@ -0,0 +1,129 @@ + +[none] +mech none +ngrains 1 + + +[Grain1] +(gauss) phi1 358.98 Phi 65.62 phi2 24.48 +[Grain2] +(gauss) phi1 121.05 Phi 176.11 phi2 295.73 +[Grain3] +(gauss) phi1 43.79 Phi 113.76 phi2 345.90 +[Grain4] +(gauss) phi1 265.15 Phi 62.52 phi2 299.71 +[Grain5] +(gauss) phi1 221.23 Phi 26.54 phi2 207.05 +[Grain6] +(gauss) phi1 249.81 Phi 61.47 phi2 152.14 +[Grain7] +(gauss) phi1 332.45 Phi 99.16 phi2 345.34 +[Grain8] +(gauss) phi1 312.27 Phi 118.27 phi2 181.59 +[Grain9] +(gauss) phi1 303.10 Phi 48.21 phi2 358.03 +[Grain10] +(gauss) phi1 338.26 Phi 48.11 phi2 176.78 +[Grain11] +(gauss) phi1 115.17 Phi 56.54 phi2 223.84 +[Grain12] +(gauss) phi1 281.04 Phi 97.48 phi2 27.94 + + +[Grain1] +crystallite 1 +(constituent) phase 1 texture 1 fraction 1.0 +[Grain2] +crystallite 1 +(constituent) phase 1 texture 2 fraction 1.0 +[Grain3] +crystallite 1 +(constituent) phase 1 texture 3 fraction 1.0 +[Grain4] +crystallite 1 +(constituent) phase 1 texture 4 fraction 1.0 +[Grain5] +crystallite 1 +(constituent) phase 1 texture 5 fraction 1.0 +[Grain6] +crystallite 1 +(constituent) phase 1 texture 6 fraction 1.0 +[Grain7] +crystallite 1 +(constituent) phase 2 texture 7 fraction 1.0 +[Grain8] +crystallite 1 +(constituent) phase 2 texture 8 fraction 1.0 +[Grain9] +crystallite 1 +(constituent) phase 2 texture 9 fraction 1.0 +[Grain10] +crystallite 1 +(constituent) phase 2 texture 10 fraction 1.0 +[Grain11] +crystallite 1 +(constituent) phase 2 texture 11 fraction 1.0 +[Grain12] +crystallite 1 +(constituent) phase 2 texture 12 fraction 1.0 + + +[pheno_fcc] +elasticity hooke +plasticity phenopowerlaw + +(output) orientation # quaternion +(output) F # deformation gradient tensor +(output) Fe # elastic deformation gradient tensor +(output) Fp # plastic deformation gradient tensor +(output) P # first Piola-Kichhoff stress tensor +(output) Lp # plastic velocity gradient tensor + + +lattice_structure fcc +Nslip 12 # per family +Ntwin 0 # per family + +c11 106.75e9 +c12 60.41e9 +c44 28.34e9 + +gdot0_slip 0.001 +n_slip 20 +tau0_slip 31e6 # per family +tausat_slip 63e6 # per family +a_slip 2.25 +h0_slipslip 75e6 +interaction_slipslip 1 1 1.4 1.4 1.4 1.4 +atol_resistance 1 + +[pheno_bcc] +elasticity hooke +plasticity phenopowerlaw + +(output) orientation # quaternion +(output) F # deformation gradient tensor +(output) Fe # elastic deformation gradient tensor +(output) Fp # plastic deformation gradient tensor +(output) P # first Piola-Kichhoff stress tensor +(output) Lp # plastic velocity gradient tensor + + +lattice_structure bcc +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 +atol_resistance 1 + + +[dummy] diff --git a/python/tests/reference/DADF5/tensionY.load b/python/tests/reference/DADF5/tensionY.load new file mode 100644 index 000000000..9332144d8 --- /dev/null +++ b/python/tests/reference/DADF5/tensionY.load @@ -0,0 +1 @@ +fdot * 0 0 0 1.0e-3 0 0 0 * stress 0 * * * * * * * 0 time 20 incs 40 freq 4 diff --git a/python/tests/reference/Geom/clean_stencil=1.geom b/python/tests/reference/Geom/clean_stencil=1.geom new file mode 100644 index 000000000..2fe5314fe --- /dev/null +++ b/python/tests/reference/Geom/clean_stencil=1.geom @@ -0,0 +1,25 @@ +4 header +grid a 8 b 5 c 4 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 22 2 2 1 21 + 1 1 6 26 2 2 5 25 + 1 1 10 30 2 2 9 29 + 1 1 14 34 2 2 13 33 + 1 1 18 38 2 2 17 37 + 1 1 3 23 2 2 2 22 + 1 1 7 27 2 2 6 26 + 1 1 11 31 2 2 10 30 + 1 1 15 35 2 2 14 34 + 1 1 19 39 2 2 18 38 + 1 1 4 24 2 2 3 23 + 1 1 8 28 2 2 7 27 + 1 1 12 32 2 2 11 31 + 1 1 16 36 2 2 15 35 + 1 1 20 40 2 2 19 39 + 1 1 5 25 2 2 4 24 + 1 1 9 29 2 2 8 28 + 1 1 13 33 2 2 12 32 + 1 1 17 37 2 2 16 36 + 1 1 21 41 2 2 20 40 diff --git a/python/tests/reference/Geom/clean_stencil=2.geom b/python/tests/reference/Geom/clean_stencil=2.geom new file mode 100644 index 000000000..f074fea56 --- /dev/null +++ b/python/tests/reference/Geom/clean_stencil=2.geom @@ -0,0 +1,25 @@ +4 header +grid a 8 b 5 c 4 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 1 2 2 2 1 1 + 1 1 1 2 2 2 2 1 + 1 1 1 6 2 2 2 5 + 1 1 1 10 2 2 2 9 + 1 1 1 14 2 2 2 13 + 1 1 1 2 2 2 2 1 + 1 1 1 2 2 2 2 1 + 1 1 1 6 2 2 2 5 + 1 1 1 10 2 2 2 9 + 1 1 1 14 2 2 2 13 + 1 1 1 3 2 2 2 2 + 1 1 1 3 2 2 2 2 + 1 1 1 7 2 2 2 6 + 1 1 1 11 2 2 2 10 + 1 1 1 15 2 2 2 14 + 1 1 1 4 2 2 2 3 + 1 1 1 4 2 2 2 3 + 1 1 1 8 2 2 2 7 + 1 1 1 12 2 2 2 11 + 1 1 1 16 2 2 2 15 diff --git a/python/tests/reference/Geom/clean_stencil=3.geom b/python/tests/reference/Geom/clean_stencil=3.geom new file mode 100644 index 000000000..63e1dce5a --- /dev/null +++ b/python/tests/reference/Geom/clean_stencil=3.geom @@ -0,0 +1,25 @@ +4 header +grid a 8 b 5 c 4 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 1 2 2 2 2 21 + 1 1 1 2 2 2 2 21 + 1 1 1 2 2 2 2 25 + 1 1 1 2 2 2 2 29 + 1 1 1 2 2 2 2 37 + 1 1 1 2 2 2 2 21 + 1 1 1 2 2 2 2 21 + 1 1 1 2 2 2 2 25 + 1 1 1 2 2 2 2 29 + 1 1 1 2 2 2 2 37 + 1 1 1 2 2 2 2 22 + 1 1 1 2 2 2 2 22 + 1 1 1 2 2 2 2 26 + 1 1 1 2 2 2 2 30 + 1 1 1 2 2 2 2 38 + 1 1 1 2 2 2 2 24 + 1 1 1 2 2 2 2 24 + 1 1 1 2 2 2 2 28 + 1 1 1 2 2 2 2 32 + 1 1 1 2 2 2 2 40 diff --git a/python/tests/reference/Geom/clean_stencil=4.geom b/python/tests/reference/Geom/clean_stencil=4.geom new file mode 100644 index 000000000..eef322d3f --- /dev/null +++ b/python/tests/reference/Geom/clean_stencil=4.geom @@ -0,0 +1,25 @@ +4 header +grid a 8 b 5 c 4 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 +1 1 1 2 2 2 2 2 +1 1 1 2 2 2 2 2 +1 1 1 2 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 2 2 2 2 2 +1 1 1 2 2 2 2 2 +1 1 1 2 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 2 2 2 2 2 +1 1 1 2 2 2 2 2 +1 1 1 2 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 1 2 2 2 2 +1 1 1 1 2 2 2 2 diff --git a/python/tests/reference/Geom/mirror_directions=x-y-z_reflect=True.geom b/python/tests/reference/Geom/mirror_directions=x-y-z_reflect=True.geom new file mode 100644 index 000000000..77ff709d7 --- /dev/null +++ b/python/tests/reference/Geom/mirror_directions=x-y-z_reflect=True.geom @@ -0,0 +1,85 @@ +4 header +grid a 16 b 10 c 8 +size x 1.6e-05 y 1e-05 z 8e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 22 2 2 1 21 21 1 2 2 22 2 1 1 + 1 1 6 26 2 2 5 25 25 5 2 2 26 6 1 1 + 1 1 10 30 2 2 9 29 29 9 2 2 30 10 1 1 + 1 1 14 34 2 2 13 33 33 13 2 2 34 14 1 1 + 1 1 18 38 2 2 17 37 37 17 2 2 38 18 1 1 + 1 1 18 38 2 2 17 37 37 17 2 2 38 18 1 1 + 1 1 14 34 2 2 13 33 33 13 2 2 34 14 1 1 + 1 1 10 30 2 2 9 29 29 9 2 2 30 10 1 1 + 1 1 6 26 2 2 5 25 25 5 2 2 26 6 1 1 + 1 1 2 22 2 2 1 21 21 1 2 2 22 2 1 1 + 1 1 3 23 2 2 2 22 22 2 2 2 23 3 1 1 + 1 1 7 27 2 2 6 26 26 6 2 2 27 7 1 1 + 1 1 11 31 2 2 10 30 30 10 2 2 31 11 1 1 + 1 1 15 35 2 2 14 34 34 14 2 2 35 15 1 1 + 1 1 19 39 2 2 18 38 38 18 2 2 39 19 1 1 + 1 1 19 39 2 2 18 38 38 18 2 2 39 19 1 1 + 1 1 15 35 2 2 14 34 34 14 2 2 35 15 1 1 + 1 1 11 31 2 2 10 30 30 10 2 2 31 11 1 1 + 1 1 7 27 2 2 6 26 26 6 2 2 27 7 1 1 + 1 1 3 23 2 2 2 22 22 2 2 2 23 3 1 1 + 1 1 4 24 2 2 3 23 23 3 2 2 24 4 1 1 + 1 1 8 28 2 2 7 27 27 7 2 2 28 8 1 1 + 1 1 12 32 2 2 11 31 31 11 2 2 32 12 1 1 + 1 1 16 36 2 2 15 35 35 15 2 2 36 16 1 1 + 1 1 20 40 2 2 19 39 39 19 2 2 40 20 1 1 + 1 1 20 40 2 2 19 39 39 19 2 2 40 20 1 1 + 1 1 16 36 2 2 15 35 35 15 2 2 36 16 1 1 + 1 1 12 32 2 2 11 31 31 11 2 2 32 12 1 1 + 1 1 8 28 2 2 7 27 27 7 2 2 28 8 1 1 + 1 1 4 24 2 2 3 23 23 3 2 2 24 4 1 1 + 1 1 5 25 2 2 4 24 24 4 2 2 25 5 1 1 + 1 1 9 29 2 2 8 28 28 8 2 2 29 9 1 1 + 1 1 13 33 2 2 12 32 32 12 2 2 33 13 1 1 + 1 1 17 37 2 2 16 36 36 16 2 2 37 17 1 1 + 1 1 21 41 2 2 20 40 40 20 2 2 41 21 1 1 + 1 1 21 41 2 2 20 40 40 20 2 2 41 21 1 1 + 1 1 17 37 2 2 16 36 36 16 2 2 37 17 1 1 + 1 1 13 33 2 2 12 32 32 12 2 2 33 13 1 1 + 1 1 9 29 2 2 8 28 28 8 2 2 29 9 1 1 + 1 1 5 25 2 2 4 24 24 4 2 2 25 5 1 1 + 1 1 5 25 2 2 4 24 24 4 2 2 25 5 1 1 + 1 1 9 29 2 2 8 28 28 8 2 2 29 9 1 1 + 1 1 13 33 2 2 12 32 32 12 2 2 33 13 1 1 + 1 1 17 37 2 2 16 36 36 16 2 2 37 17 1 1 + 1 1 21 41 2 2 20 40 40 20 2 2 41 21 1 1 + 1 1 21 41 2 2 20 40 40 20 2 2 41 21 1 1 + 1 1 17 37 2 2 16 36 36 16 2 2 37 17 1 1 + 1 1 13 33 2 2 12 32 32 12 2 2 33 13 1 1 + 1 1 9 29 2 2 8 28 28 8 2 2 29 9 1 1 + 1 1 5 25 2 2 4 24 24 4 2 2 25 5 1 1 + 1 1 4 24 2 2 3 23 23 3 2 2 24 4 1 1 + 1 1 8 28 2 2 7 27 27 7 2 2 28 8 1 1 + 1 1 12 32 2 2 11 31 31 11 2 2 32 12 1 1 + 1 1 16 36 2 2 15 35 35 15 2 2 36 16 1 1 + 1 1 20 40 2 2 19 39 39 19 2 2 40 20 1 1 + 1 1 20 40 2 2 19 39 39 19 2 2 40 20 1 1 + 1 1 16 36 2 2 15 35 35 15 2 2 36 16 1 1 + 1 1 12 32 2 2 11 31 31 11 2 2 32 12 1 1 + 1 1 8 28 2 2 7 27 27 7 2 2 28 8 1 1 + 1 1 4 24 2 2 3 23 23 3 2 2 24 4 1 1 + 1 1 3 23 2 2 2 22 22 2 2 2 23 3 1 1 + 1 1 7 27 2 2 6 26 26 6 2 2 27 7 1 1 + 1 1 11 31 2 2 10 30 30 10 2 2 31 11 1 1 + 1 1 15 35 2 2 14 34 34 14 2 2 35 15 1 1 + 1 1 19 39 2 2 18 38 38 18 2 2 39 19 1 1 + 1 1 19 39 2 2 18 38 38 18 2 2 39 19 1 1 + 1 1 15 35 2 2 14 34 34 14 2 2 35 15 1 1 + 1 1 11 31 2 2 10 30 30 10 2 2 31 11 1 1 + 1 1 7 27 2 2 6 26 26 6 2 2 27 7 1 1 + 1 1 3 23 2 2 2 22 22 2 2 2 23 3 1 1 + 1 1 2 22 2 2 1 21 21 1 2 2 22 2 1 1 + 1 1 6 26 2 2 5 25 25 5 2 2 26 6 1 1 + 1 1 10 30 2 2 9 29 29 9 2 2 30 10 1 1 + 1 1 14 34 2 2 13 33 33 13 2 2 34 14 1 1 + 1 1 18 38 2 2 17 37 37 17 2 2 38 18 1 1 + 1 1 18 38 2 2 17 37 37 17 2 2 38 18 1 1 + 1 1 14 34 2 2 13 33 33 13 2 2 34 14 1 1 + 1 1 10 30 2 2 9 29 29 9 2 2 30 10 1 1 + 1 1 6 26 2 2 5 25 25 5 2 2 26 6 1 1 + 1 1 2 22 2 2 1 21 21 1 2 2 22 2 1 1 diff --git a/python/tests/reference/Geom/mirror_directions=x_reflect=False.geom b/python/tests/reference/Geom/mirror_directions=x_reflect=False.geom new file mode 100644 index 000000000..afb3bb5f8 --- /dev/null +++ b/python/tests/reference/Geom/mirror_directions=x_reflect=False.geom @@ -0,0 +1,25 @@ +4 header +grid a 14 b 5 c 4 +size x 1.4e-05 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 22 2 2 1 21 1 2 2 22 2 1 + 1 1 6 26 2 2 5 25 5 2 2 26 6 1 + 1 1 10 30 2 2 9 29 9 2 2 30 10 1 + 1 1 14 34 2 2 13 33 13 2 2 34 14 1 + 1 1 18 38 2 2 17 37 17 2 2 38 18 1 + 1 1 3 23 2 2 2 22 2 2 2 23 3 1 + 1 1 7 27 2 2 6 26 6 2 2 27 7 1 + 1 1 11 31 2 2 10 30 10 2 2 31 11 1 + 1 1 15 35 2 2 14 34 14 2 2 35 15 1 + 1 1 19 39 2 2 18 38 18 2 2 39 19 1 + 1 1 4 24 2 2 3 23 3 2 2 24 4 1 + 1 1 8 28 2 2 7 27 7 2 2 28 8 1 + 1 1 12 32 2 2 11 31 11 2 2 32 12 1 + 1 1 16 36 2 2 15 35 15 2 2 36 16 1 + 1 1 20 40 2 2 19 39 19 2 2 40 20 1 + 1 1 5 25 2 2 4 24 4 2 2 25 5 1 + 1 1 9 29 2 2 8 28 8 2 2 29 9 1 + 1 1 13 33 2 2 12 32 12 2 2 33 13 1 + 1 1 17 37 2 2 16 36 16 2 2 37 17 1 + 1 1 21 41 2 2 20 40 20 2 2 41 21 1 diff --git a/python/tests/reference/Geom/mirror_directions=y-z_reflect=False.geom b/python/tests/reference/Geom/mirror_directions=y-z_reflect=False.geom new file mode 100644 index 000000000..37d8ae18e --- /dev/null +++ b/python/tests/reference/Geom/mirror_directions=y-z_reflect=False.geom @@ -0,0 +1,53 @@ +4 header +grid a 8 b 8 c 6 +size x 8e-06 y 8.000000000000001e-06 z 6e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 22 2 2 1 21 + 1 1 6 26 2 2 5 25 + 1 1 10 30 2 2 9 29 + 1 1 14 34 2 2 13 33 + 1 1 18 38 2 2 17 37 + 1 1 14 34 2 2 13 33 + 1 1 10 30 2 2 9 29 + 1 1 6 26 2 2 5 25 + 1 1 3 23 2 2 2 22 + 1 1 7 27 2 2 6 26 + 1 1 11 31 2 2 10 30 + 1 1 15 35 2 2 14 34 + 1 1 19 39 2 2 18 38 + 1 1 15 35 2 2 14 34 + 1 1 11 31 2 2 10 30 + 1 1 7 27 2 2 6 26 + 1 1 4 24 2 2 3 23 + 1 1 8 28 2 2 7 27 + 1 1 12 32 2 2 11 31 + 1 1 16 36 2 2 15 35 + 1 1 20 40 2 2 19 39 + 1 1 16 36 2 2 15 35 + 1 1 12 32 2 2 11 31 + 1 1 8 28 2 2 7 27 + 1 1 5 25 2 2 4 24 + 1 1 9 29 2 2 8 28 + 1 1 13 33 2 2 12 32 + 1 1 17 37 2 2 16 36 + 1 1 21 41 2 2 20 40 + 1 1 17 37 2 2 16 36 + 1 1 13 33 2 2 12 32 + 1 1 9 29 2 2 8 28 + 1 1 4 24 2 2 3 23 + 1 1 8 28 2 2 7 27 + 1 1 12 32 2 2 11 31 + 1 1 16 36 2 2 15 35 + 1 1 20 40 2 2 19 39 + 1 1 16 36 2 2 15 35 + 1 1 12 32 2 2 11 31 + 1 1 8 28 2 2 7 27 + 1 1 3 23 2 2 2 22 + 1 1 7 27 2 2 6 26 + 1 1 11 31 2 2 10 30 + 1 1 15 35 2 2 14 34 + 1 1 19 39 2 2 18 38 + 1 1 15 35 2 2 14 34 + 1 1 11 31 2 2 10 30 + 1 1 7 27 2 2 6 26 diff --git a/python/tests/reference/Geom/mirror_directions=z-x-y_reflect=False.geom b/python/tests/reference/Geom/mirror_directions=z-x-y_reflect=False.geom new file mode 100644 index 000000000..5d7c23eb0 --- /dev/null +++ b/python/tests/reference/Geom/mirror_directions=z-x-y_reflect=False.geom @@ -0,0 +1,53 @@ +4 header +grid a 14 b 8 c 6 +size x 1.4e-05 y 8.000000000000001e-06 z 6e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 22 2 2 1 21 1 2 2 22 2 1 + 1 1 6 26 2 2 5 25 5 2 2 26 6 1 + 1 1 10 30 2 2 9 29 9 2 2 30 10 1 + 1 1 14 34 2 2 13 33 13 2 2 34 14 1 + 1 1 18 38 2 2 17 37 17 2 2 38 18 1 + 1 1 14 34 2 2 13 33 13 2 2 34 14 1 + 1 1 10 30 2 2 9 29 9 2 2 30 10 1 + 1 1 6 26 2 2 5 25 5 2 2 26 6 1 + 1 1 3 23 2 2 2 22 2 2 2 23 3 1 + 1 1 7 27 2 2 6 26 6 2 2 27 7 1 + 1 1 11 31 2 2 10 30 10 2 2 31 11 1 + 1 1 15 35 2 2 14 34 14 2 2 35 15 1 + 1 1 19 39 2 2 18 38 18 2 2 39 19 1 + 1 1 15 35 2 2 14 34 14 2 2 35 15 1 + 1 1 11 31 2 2 10 30 10 2 2 31 11 1 + 1 1 7 27 2 2 6 26 6 2 2 27 7 1 + 1 1 4 24 2 2 3 23 3 2 2 24 4 1 + 1 1 8 28 2 2 7 27 7 2 2 28 8 1 + 1 1 12 32 2 2 11 31 11 2 2 32 12 1 + 1 1 16 36 2 2 15 35 15 2 2 36 16 1 + 1 1 20 40 2 2 19 39 19 2 2 40 20 1 + 1 1 16 36 2 2 15 35 15 2 2 36 16 1 + 1 1 12 32 2 2 11 31 11 2 2 32 12 1 + 1 1 8 28 2 2 7 27 7 2 2 28 8 1 + 1 1 5 25 2 2 4 24 4 2 2 25 5 1 + 1 1 9 29 2 2 8 28 8 2 2 29 9 1 + 1 1 13 33 2 2 12 32 12 2 2 33 13 1 + 1 1 17 37 2 2 16 36 16 2 2 37 17 1 + 1 1 21 41 2 2 20 40 20 2 2 41 21 1 + 1 1 17 37 2 2 16 36 16 2 2 37 17 1 + 1 1 13 33 2 2 12 32 12 2 2 33 13 1 + 1 1 9 29 2 2 8 28 8 2 2 29 9 1 + 1 1 4 24 2 2 3 23 3 2 2 24 4 1 + 1 1 8 28 2 2 7 27 7 2 2 28 8 1 + 1 1 12 32 2 2 11 31 11 2 2 32 12 1 + 1 1 16 36 2 2 15 35 15 2 2 36 16 1 + 1 1 20 40 2 2 19 39 19 2 2 40 20 1 + 1 1 16 36 2 2 15 35 15 2 2 36 16 1 + 1 1 12 32 2 2 11 31 11 2 2 32 12 1 + 1 1 8 28 2 2 7 27 7 2 2 28 8 1 + 1 1 3 23 2 2 2 22 2 2 2 23 3 1 + 1 1 7 27 2 2 6 26 6 2 2 27 7 1 + 1 1 11 31 2 2 10 30 10 2 2 31 11 1 + 1 1 15 35 2 2 14 34 14 2 2 35 15 1 + 1 1 19 39 2 2 18 38 18 2 2 39 19 1 + 1 1 15 35 2 2 14 34 14 2 2 35 15 1 + 1 1 11 31 2 2 10 30 10 2 2 31 11 1 + 1 1 7 27 2 2 6 26 6 2 2 27 7 1 diff --git a/python/tests/reference/Geom/scale_grid=10-10-10.geom b/python/tests/reference/Geom/scale_grid=10-10-10.geom new file mode 100644 index 000000000..43587a615 --- /dev/null +++ b/python/tests/reference/Geom/scale_grid=10-10-10.geom @@ -0,0 +1,105 @@ +4 header +grid a 10 b 10 c 10 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 2 22 2 2 2 1 21 + 1 1 2 2 22 2 2 2 1 21 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 18 18 38 2 2 2 17 37 + 1 1 18 18 38 2 2 2 17 37 + 1 1 2 2 22 2 2 2 1 21 + 1 1 2 2 22 2 2 2 1 21 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 18 18 38 2 2 2 17 37 + 1 1 18 18 38 2 2 2 17 37 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 5 5 25 2 2 2 4 24 + 1 1 5 5 25 2 2 2 4 24 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 21 21 41 2 2 2 20 40 + 1 1 21 21 41 2 2 2 20 40 + 1 1 5 5 25 2 2 2 4 24 + 1 1 5 5 25 2 2 2 4 24 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 21 21 41 2 2 2 20 40 + 1 1 21 21 41 2 2 2 20 40 diff --git a/python/tests/reference/Geom/scale_grid=10-11-10.geom b/python/tests/reference/Geom/scale_grid=10-11-10.geom new file mode 100644 index 000000000..e12fc64fc --- /dev/null +++ b/python/tests/reference/Geom/scale_grid=10-11-10.geom @@ -0,0 +1,115 @@ +4 header +grid a 10 b 11 c 10 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 2 22 2 2 2 1 21 + 1 1 2 2 22 2 2 2 1 21 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 18 18 38 2 2 2 17 37 + 1 1 18 18 38 2 2 2 17 37 + 1 1 2 2 22 2 2 2 1 21 + 1 1 2 2 22 2 2 2 1 21 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 18 18 38 2 2 2 17 37 + 1 1 18 18 38 2 2 2 17 37 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 5 5 25 2 2 2 4 24 + 1 1 5 5 25 2 2 2 4 24 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 21 21 41 2 2 2 20 40 + 1 1 21 21 41 2 2 2 20 40 + 1 1 5 5 25 2 2 2 4 24 + 1 1 5 5 25 2 2 2 4 24 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 21 21 41 2 2 2 20 40 + 1 1 21 21 41 2 2 2 20 40 diff --git a/python/tests/reference/Geom/scale_grid=10-13-10.geom b/python/tests/reference/Geom/scale_grid=10-13-10.geom new file mode 100644 index 000000000..cbe4afc00 --- /dev/null +++ b/python/tests/reference/Geom/scale_grid=10-13-10.geom @@ -0,0 +1,135 @@ +4 header +grid a 10 b 13 c 10 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 2 22 2 2 2 1 21 + 1 1 2 2 22 2 2 2 1 21 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 18 18 38 2 2 2 17 37 + 1 1 18 18 38 2 2 2 17 37 + 1 1 2 2 22 2 2 2 1 21 + 1 1 2 2 22 2 2 2 1 21 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 18 18 38 2 2 2 17 37 + 1 1 18 18 38 2 2 2 17 37 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 3 3 23 2 2 2 2 22 + 1 1 3 3 23 2 2 2 2 22 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 7 7 27 2 2 2 6 26 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 11 11 31 2 2 2 10 30 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 15 15 35 2 2 2 14 34 + 1 1 19 19 39 2 2 2 18 38 + 1 1 19 19 39 2 2 2 18 38 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 4 4 24 2 2 2 3 23 + 1 1 4 4 24 2 2 2 3 23 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 8 8 28 2 2 2 7 27 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 12 12 32 2 2 2 11 31 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 16 16 36 2 2 2 15 35 + 1 1 20 20 40 2 2 2 19 39 + 1 1 20 20 40 2 2 2 19 39 + 1 1 5 5 25 2 2 2 4 24 + 1 1 5 5 25 2 2 2 4 24 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 21 21 41 2 2 2 20 40 + 1 1 21 21 41 2 2 2 20 40 + 1 1 5 5 25 2 2 2 4 24 + 1 1 5 5 25 2 2 2 4 24 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 21 21 41 2 2 2 20 40 + 1 1 21 21 41 2 2 2 20 40 diff --git a/python/tests/reference/Geom/scale_grid=10-20-2.geom b/python/tests/reference/Geom/scale_grid=10-20-2.geom new file mode 100644 index 000000000..6b1888f17 --- /dev/null +++ b/python/tests/reference/Geom/scale_grid=10-20-2.geom @@ -0,0 +1,45 @@ +4 header +grid a 10 b 20 c 2 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 2 22 2 2 2 1 21 + 1 1 2 2 22 2 2 2 1 21 + 1 1 2 2 22 2 2 2 1 21 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 6 6 26 2 2 2 5 25 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 10 10 30 2 2 2 9 29 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 14 14 34 2 2 2 13 33 + 1 1 18 18 38 2 2 2 17 37 + 1 1 18 18 38 2 2 2 17 37 + 1 1 18 18 38 2 2 2 17 37 + 1 1 5 5 25 2 2 2 4 24 + 1 1 5 5 25 2 2 2 4 24 + 1 1 5 5 25 2 2 2 4 24 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 9 9 29 2 2 2 8 28 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 13 13 33 2 2 2 12 32 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 17 17 37 2 2 2 16 36 + 1 1 21 21 41 2 2 2 20 40 + 1 1 21 21 41 2 2 2 20 40 + 1 1 21 21 41 2 2 2 20 40 diff --git a/python/tests/reference/Geom/scale_grid=5-4-20.geom b/python/tests/reference/Geom/scale_grid=5-4-20.geom new file mode 100644 index 000000000..043683f6a --- /dev/null +++ b/python/tests/reference/Geom/scale_grid=5-4-20.geom @@ -0,0 +1,85 @@ +4 header +grid a 5 b 4 c 20 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 2 2 2 21 + 1 6 2 2 25 + 1 14 2 2 33 + 1 18 2 2 37 + 1 2 2 2 21 + 1 6 2 2 25 + 1 14 2 2 33 + 1 18 2 2 37 + 1 2 2 2 21 + 1 6 2 2 25 + 1 14 2 2 33 + 1 18 2 2 37 + 1 2 2 2 21 + 1 6 2 2 25 + 1 14 2 2 33 + 1 18 2 2 37 + 1 3 2 2 22 + 1 7 2 2 26 + 1 15 2 2 34 + 1 19 2 2 38 + 1 3 2 2 22 + 1 7 2 2 26 + 1 15 2 2 34 + 1 19 2 2 38 + 1 3 2 2 22 + 1 7 2 2 26 + 1 15 2 2 34 + 1 19 2 2 38 + 1 3 2 2 22 + 1 7 2 2 26 + 1 15 2 2 34 + 1 19 2 2 38 + 1 3 2 2 22 + 1 7 2 2 26 + 1 15 2 2 34 + 1 19 2 2 38 + 1 3 2 2 22 + 1 7 2 2 26 + 1 15 2 2 34 + 1 19 2 2 38 + 1 4 2 2 23 + 1 8 2 2 27 + 1 16 2 2 35 + 1 20 2 2 39 + 1 4 2 2 23 + 1 8 2 2 27 + 1 16 2 2 35 + 1 20 2 2 39 + 1 4 2 2 23 + 1 8 2 2 27 + 1 16 2 2 35 + 1 20 2 2 39 + 1 4 2 2 23 + 1 8 2 2 27 + 1 16 2 2 35 + 1 20 2 2 39 + 1 4 2 2 23 + 1 8 2 2 27 + 1 16 2 2 35 + 1 20 2 2 39 + 1 4 2 2 23 + 1 8 2 2 27 + 1 16 2 2 35 + 1 20 2 2 39 + 1 5 2 2 24 + 1 9 2 2 28 + 1 17 2 2 36 + 1 21 2 2 40 + 1 5 2 2 24 + 1 9 2 2 28 + 1 17 2 2 36 + 1 21 2 2 40 + 1 5 2 2 24 + 1 9 2 2 28 + 1 17 2 2 36 + 1 21 2 2 40 + 1 5 2 2 24 + 1 9 2 2 28 + 1 17 2 2 36 + 1 21 2 2 40 diff --git a/python/tests/reference/Geom/scale_grid=8-10-12.geom b/python/tests/reference/Geom/scale_grid=8-10-12.geom new file mode 100644 index 000000000..5cfe66aba --- /dev/null +++ b/python/tests/reference/Geom/scale_grid=8-10-12.geom @@ -0,0 +1,125 @@ +4 header +grid a 8 b 10 c 12 +size x 8e-06 y 5e-06 z 4e-06 +origin x 0.0 y 0.0 z 0.0 +homogenization 1 + 1 1 2 22 2 2 1 21 + 1 1 2 22 2 2 1 21 + 1 1 6 26 2 2 5 25 + 1 1 6 26 2 2 5 25 + 1 1 10 30 2 2 9 29 + 1 1 10 30 2 2 9 29 + 1 1 14 34 2 2 13 33 + 1 1 14 34 2 2 13 33 + 1 1 18 38 2 2 17 37 + 1 1 18 38 2 2 17 37 + 1 1 2 22 2 2 1 21 + 1 1 2 22 2 2 1 21 + 1 1 6 26 2 2 5 25 + 1 1 6 26 2 2 5 25 + 1 1 10 30 2 2 9 29 + 1 1 10 30 2 2 9 29 + 1 1 14 34 2 2 13 33 + 1 1 14 34 2 2 13 33 + 1 1 18 38 2 2 17 37 + 1 1 18 38 2 2 17 37 + 1 1 3 23 2 2 2 22 + 1 1 3 23 2 2 2 22 + 1 1 7 27 2 2 6 26 + 1 1 7 27 2 2 6 26 + 1 1 11 31 2 2 10 30 + 1 1 11 31 2 2 10 30 + 1 1 15 35 2 2 14 34 + 1 1 15 35 2 2 14 34 + 1 1 19 39 2 2 18 38 + 1 1 19 39 2 2 18 38 + 1 1 3 23 2 2 2 22 + 1 1 3 23 2 2 2 22 + 1 1 7 27 2 2 6 26 + 1 1 7 27 2 2 6 26 + 1 1 11 31 2 2 10 30 + 1 1 11 31 2 2 10 30 + 1 1 15 35 2 2 14 34 + 1 1 15 35 2 2 14 34 + 1 1 19 39 2 2 18 38 + 1 1 19 39 2 2 18 38 + 1 1 3 23 2 2 2 22 + 1 1 3 23 2 2 2 22 + 1 1 7 27 2 2 6 26 + 1 1 7 27 2 2 6 26 + 1 1 11 31 2 2 10 30 + 1 1 11 31 2 2 10 30 + 1 1 15 35 2 2 14 34 + 1 1 15 35 2 2 14 34 + 1 1 19 39 2 2 18 38 + 1 1 19 39 2 2 18 38 + 1 1 3 23 2 2 2 22 + 1 1 3 23 2 2 2 22 + 1 1 7 27 2 2 6 26 + 1 1 7 27 2 2 6 26 + 1 1 11 31 2 2 10 30 + 1 1 11 31 2 2 10 30 + 1 1 15 35 2 2 14 34 + 1 1 15 35 2 2 14 34 + 1 1 19 39 2 2 18 38 + 1 1 19 39 2 2 18 38 + 1 1 4 24 2 2 3 23 + 1 1 4 24 2 2 3 23 + 1 1 8 28 2 2 7 27 + 1 1 8 28 2 2 7 27 + 1 1 12 32 2 2 11 31 + 1 1 12 32 2 2 11 31 + 1 1 16 36 2 2 15 35 + 1 1 16 36 2 2 15 35 + 1 1 20 40 2 2 19 39 + 1 1 20 40 2 2 19 39 + 1 1 4 24 2 2 3 23 + 1 1 4 24 2 2 3 23 + 1 1 8 28 2 2 7 27 + 1 1 8 28 2 2 7 27 + 1 1 12 32 2 2 11 31 + 1 1 12 32 2 2 11 31 + 1 1 16 36 2 2 15 35 + 1 1 16 36 2 2 15 35 + 1 1 20 40 2 2 19 39 + 1 1 20 40 2 2 19 39 + 1 1 4 24 2 2 3 23 + 1 1 4 24 2 2 3 23 + 1 1 8 28 2 2 7 27 + 1 1 8 28 2 2 7 27 + 1 1 12 32 2 2 11 31 + 1 1 12 32 2 2 11 31 + 1 1 16 36 2 2 15 35 + 1 1 16 36 2 2 15 35 + 1 1 20 40 2 2 19 39 + 1 1 20 40 2 2 19 39 + 1 1 4 24 2 2 3 23 + 1 1 4 24 2 2 3 23 + 1 1 8 28 2 2 7 27 + 1 1 8 28 2 2 7 27 + 1 1 12 32 2 2 11 31 + 1 1 12 32 2 2 11 31 + 1 1 16 36 2 2 15 35 + 1 1 16 36 2 2 15 35 + 1 1 20 40 2 2 19 39 + 1 1 20 40 2 2 19 39 + 1 1 5 25 2 2 4 24 + 1 1 5 25 2 2 4 24 + 1 1 9 29 2 2 8 28 + 1 1 9 29 2 2 8 28 + 1 1 13 33 2 2 12 32 + 1 1 13 33 2 2 12 32 + 1 1 17 37 2 2 16 36 + 1 1 17 37 2 2 16 36 + 1 1 21 41 2 2 20 40 + 1 1 21 41 2 2 20 40 + 1 1 5 25 2 2 4 24 + 1 1 5 25 2 2 4 24 + 1 1 9 29 2 2 8 28 + 1 1 9 29 2 2 8 28 + 1 1 13 33 2 2 12 32 + 1 1 13 33 2 2 12 32 + 1 1 17 37 2 2 16 36 + 1 1 17 37 2 2 16 36 + 1 1 21 41 2 2 20 40 + 1 1 21 41 2 2 20 40 diff --git a/python/tests/reference/Table/datatype-mix.txt b/python/tests/reference/Table/datatype-mix.txt new file mode 100644 index 000000000..2f6baa852 --- /dev/null +++ b/python/tests/reference/Table/datatype-mix.txt @@ -0,0 +1,4 @@ +1 header +a b +1.0 hallo +0.1 "hallo test" diff --git a/python/tests/reference/Table/whitespace-mix.txt b/python/tests/reference/Table/whitespace-mix.txt new file mode 100644 index 000000000..933a16e77 --- /dev/null +++ b/python/tests/reference/Table/whitespace-mix.txt @@ -0,0 +1,6 @@ +1 header +a b 1_c 2_c +1 2 3 4 +5 6 7 8 +9 10. 12. 12 + diff --git a/python/tests/test_DADF5.py b/python/tests/test_DADF5.py new file mode 100644 index 000000000..8aa8ec174 --- /dev/null +++ b/python/tests/test_DADF5.py @@ -0,0 +1,82 @@ +import shutil +import os + +import pytest +import numpy as np + +from damask import DADF5 +from damask import mechanics + +@pytest.fixture +def default(tmp_path,reference_dir): + """Small DADF5 file in temp location for modification.""" + fname = '12grains6x7x8_tensionY.hdf5' + shutil.copy(os.path.join(reference_dir,fname),tmp_path) + f = DADF5(os.path.join(tmp_path,fname)) + f.set_by_time(20.0,20.0) + return f + +@pytest.fixture +def reference_dir(reference_dir_base): + """Directory containing reference results.""" + return os.path.join(reference_dir_base,'DADF5') + + +class TestDADF5: + + def test_time_increments(self,default): + shape = default.read_dataset(default.get_dataset_location('F'),0).shape + default.set_by_time(0.0,20.0) + for i in default.iter_visible('increments'): + assert shape == default.read_dataset(default.get_dataset_location('F'),0).shape + + + def test_add_absolute(self,default): + default.add_absolute('Fe') + loc = {'Fe': default.get_dataset_location('Fe'), + '|Fe|': default.get_dataset_location('|Fe|')} + in_memory = np.abs(default.read_dataset(loc['Fe'],0)) + in_file = default.read_dataset(loc['|Fe|'],0) + assert np.allclose(in_memory,in_file) + + def test_add_Cauchy(self,default): + default.add_Cauchy('P','F') + loc = {'F': default.get_dataset_location('F'), + 'P': default.get_dataset_location('P'), + 'sigma':default.get_dataset_location('sigma')} + in_memory = mechanics.Cauchy(default.read_dataset(loc['F'],0), + default.read_dataset(loc['P'],0)) + in_file = default.read_dataset(loc['sigma'],0) + assert np.allclose(in_memory,in_file) + + def test_add_determinant(self,default): + default.add_determinant('P') + loc = {'P': default.get_dataset_location('P'), + 'det(P)':default.get_dataset_location('det(P)')} + in_memory = np.linalg.det(default.read_dataset(loc['P'],0)).reshape((-1,1)) + in_file = default.read_dataset(loc['det(P)'],0) + assert np.allclose(in_memory,in_file) + + def test_add_deviator(self,default): + default.add_deviator('P') + loc = {'P' :default.get_dataset_location('P'), + 's_P':default.get_dataset_location('s_P')} + in_memory = mechanics.deviatoric_part(default.read_dataset(loc['P'],0)) + in_file = default.read_dataset(loc['s_P'],0) + assert np.allclose(in_memory,in_file) + + def test_add_norm(self,default): + default.add_norm('F',1) + loc = {'F': default.get_dataset_location('F'), + '|F|_1':default.get_dataset_location('|F|_1')} + in_memory = np.linalg.norm(default.read_dataset(loc['F'],0),ord=1,axis=(1,2),keepdims=True) + in_file = default.read_dataset(loc['|F|_1'],0) + assert np.allclose(in_memory,in_file) + + def test_add_spherical(self,default): + default.add_spherical('P') + loc = {'P': default.get_dataset_location('P'), + 'p_P': default.get_dataset_location('p_P')} + in_memory = mechanics.spherical_part(default.read_dataset(loc['P'],0)).reshape(-1,1) + in_file = default.read_dataset(loc['p_P'],0) + assert np.allclose(in_memory,in_file) diff --git a/python/tests/test_Geom.py b/python/tests/test_Geom.py new file mode 100644 index 000000000..bc3a3e751 --- /dev/null +++ b/python/tests/test_Geom.py @@ -0,0 +1,99 @@ +import copy +import os + +import pytest +import numpy as np + +from damask import Geom + + +def geom_equal(a,b): + return np.all(a.get_microstructure() == b.get_microstructure()) and \ + np.all(a.get_size() == b.get_size()) and \ + np.all(a.get_grid() == b.get_grid()) + +@pytest.fixture +def default(): + """Simple geometry.""" + x=np.concatenate((np.ones(40,dtype=int), + np.arange(2,42), + np.ones(40,dtype=int)*2, + np.arange(1,41))).reshape((8,5,4)) + return Geom(x,[8e-6,5e-6,4e-6]) + +@pytest.fixture +def reference_dir(reference_dir_base): + """Directory containing reference results.""" + return os.path.join(reference_dir_base,'Geom') + + +class TestGeom: + + def test_update(self,default): + modified = copy.deepcopy(default) + modified.update( + default.get_microstructure(), + default.get_size(), + default.get_origin() + ) + assert geom_equal(modified,default) + + + def test_write_read_str(self,default,tmpdir): + default.to_file(str(tmpdir.join('default.geom'))) + new = Geom.from_file(str(tmpdir.join('default.geom'))) + assert geom_equal(new,default) + + def test_write_read_file(self,default,tmpdir): + with open(tmpdir.join('default.geom'),'w') as f: + default.to_file(f) + with open(tmpdir.join('default.geom')) as f: + new = Geom.from_file(f) + assert geom_equal(new,default) + + @pytest.mark.parametrize('pack',[True,False]) + def test_pack(self,default,tmpdir,pack): + default.to_file(tmpdir.join('default.geom'),pack=pack) + new = Geom.from_file(tmpdir.join('default.geom')) + assert geom_equal(new,default) + + @pytest.mark.parametrize('directions,reflect',[ + (['x'], False), + (['x','y','z'],True), + (['z','x','y'],False), + (['y','z'], False) + ] + ) + def test_mirror(self,default,update,reference_dir,directions,reflect): + modified = copy.deepcopy(default) + modified.mirror(directions,reflect) + tag = 'directions={}_reflect={}'.format('-'.join(directions),reflect) + reference = os.path.join(reference_dir,'mirror_{}.geom'.format(tag)) + if update: modified.to_file(reference) + assert geom_equal(modified,Geom.from_file(reference)) + + @pytest.mark.parametrize('stencil',[(1),(2),(3),(4)]) + def test_clean(self,default,update,reference_dir,stencil): + modified = copy.deepcopy(default) + modified.clean(stencil) + tag = 'stencil={}'.format(stencil) + reference = os.path.join(reference_dir,'clean_{}.geom'.format(tag)) + if update: modified.to_file(reference) + assert geom_equal(modified,Geom.from_file(reference)) + + @pytest.mark.parametrize('grid',[ + ((10,11,10)), + ([10,13,10]), + (np.array((10,10,10))), + (np.array((8, 10,12))), + (np.array((5, 4, 20))), + (np.array((10,20,2)) ) + ] + ) + def test_scale(self,default,update,reference_dir,grid): + modified = copy.deepcopy(default) + modified.scale(grid) + tag = 'grid={}'.format('-'.join([str(x) for x in grid])) + reference = os.path.join(reference_dir,'scale_{}.geom'.format(tag)) + if update: modified.to_file(reference) + assert geom_equal(modified,Geom.from_file(reference)) diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py new file mode 100644 index 000000000..72956c013 --- /dev/null +++ b/python/tests/test_Rotation.py @@ -0,0 +1,55 @@ +import pytest +import numpy as np + +from damask import Rotation + +n = 1000 + +@pytest.fixture +def default(): + """A set of n random rotations.""" + return [Rotation.fromRandom() for r in range(n)] + + +class TestRotation: + + def test_Eulers(self,default): + for rot in default: + assert np.allclose(rot.asQuaternion(), + Rotation.fromEulers(rot.asEulers()).asQuaternion()) + + + def test_AxisAngle(self,default): + for rot in default: + assert np.allclose(rot.asEulers(), + Rotation.fromAxisAngle(rot.asAxisAngle()).asEulers()) + + + def test_Matrix(self,default): + for rot in default: + assert np.allclose(rot.asAxisAngle(), + Rotation.fromMatrix(rot.asMatrix()).asAxisAngle()) + + + def test_Rodriques(self,default): + for rot in default: + assert np.allclose(rot.asMatrix(), + Rotation.fromRodrigues(rot.asRodrigues()).asMatrix()) + + + def test_Homochoric(self,default): + for rot in default: + assert np.allclose(rot.asRodrigues(), + Rotation.fromHomochoric(rot.asHomochoric()).asRodrigues()) + + + def test_Cubochoric(self,default): + for rot in default: + assert np.allclose(rot.asHomochoric(), + Rotation.fromCubochoric(rot.asCubochoric()).asHomochoric()) + + + def test_Quaternion(self,default): + for rot in default: + assert np.allclose(rot.asCubochoric(), + Rotation.fromQuaternion(rot.asQuaternion()).asCubochoric()) diff --git a/python/tests/test_Table.py b/python/tests/test_Table.py new file mode 100644 index 000000000..a0dc31975 --- /dev/null +++ b/python/tests/test_Table.py @@ -0,0 +1,128 @@ +import os + +import pytest +import numpy as np + +from damask import Table + + +@pytest.fixture +def default(): + """Simple Table.""" + x = np.ones((5,13),dtype=float) + return Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['test data','contains only ones']) + +@pytest.fixture +def reference_dir(reference_dir_base): + """Directory containing reference results.""" + return os.path.join(reference_dir_base,'Table') + +class TestTable: + + def test_get_scalar(self,default): + d = default.get('s') + assert np.allclose(d,1.0) and d.shape[1:] == (1,) + + def test_get_vector(self,default): + d = default.get('v') + assert np.allclose(d,1.0) and d.shape[1:] == (3,) + + def test_get_tensor(self,default): + d = default.get('F') + assert np.allclose(d,1.0) and d.shape[1:] == (3,3) + + def test_get_component(self,default): + d = default.get('5_F') + assert np.allclose(d,1.0) and d.shape[1:] == (1,) + + def test_write_read_str(self,default,tmpdir): + default.to_ASCII(str(tmpdir.join('default.txt'))) + new = Table.from_ASCII(str(tmpdir.join('default.txt'))) + assert all(default.data==new.data) + + def test_write_read_file(self,default,tmpdir): + with open(tmpdir.join('default.txt'),'w') as f: + default.to_ASCII(f) + with open(tmpdir.join('default.txt')) as f: + new = Table.from_ASCII(f) + assert all(default.data==new.data) + + @pytest.mark.parametrize('fname',['datatype-mix.txt','whitespace-mix.txt']) + def test_read_strange(self,reference_dir,fname): + with open(os.path.join(reference_dir,fname)) as f: + Table.from_ASCII(f) + + def test_set(self,default): + default.set('F',np.zeros((5,3,3)),'set to zero') + d=default.get('F') + assert np.allclose(d,0.0) and d.shape[1:] == (3,3) + + def test_labels(self,default): + assert default.labels == ['F','v','s'] + + def test_add(self,default): + d = np.random.random((5,9)) + default.add('nine',d,'random data') + assert np.allclose(d,default.get('nine')) + + def test_rename_equivalent(self,default): + v = default.get('v') + default.rename('v','u') + u = default.get('u') + assert np.all(v == u) + + def test_rename_gone(self,default): + default.rename('v','V') + with pytest.raises(KeyError): + default.get('v') + + def test_delete(self,default): + default.delete('v') + with pytest.raises(KeyError): + default.get('v') + + + def test_invalid_initialization(self): + x = np.random.random((5,10)) + with pytest.raises(ValueError): + Table(x,{'F':(3,3)}) + + def test_invalid_set(self,default): + x = default.get('v') + with pytest.raises(ValueError): + default.set('F',x,'does not work') + + def test_invalid_get(self,default): + with pytest.raises(KeyError): + default.get('n') + + def test_sort_scalar(self): + x = np.random.random((5,13)) + t = Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['random test data']) + unsort = t.get('s') + t.sort_by('s') + sort = t.get('s') + assert np.all(np.sort(unsort,0)==sort) + + def test_sort_component(self): + x = np.random.random((5,12)) + t = Table(x,{'F':(3,3),'v':(3,)},['random test data']) + unsort = t.get('4_F') + t.sort_by('4_F') + sort = t.get('4_F') + assert np.all(np.sort(unsort,0)==sort) + + def test_sort_revert(self): + x = np.random.random((5,12)) + t = Table(x,{'F':(3,3),'v':(3,)},['random test data']) + t.sort_by('4_F',ascending=False) + sort = t.get('4_F') + assert np.all(np.sort(sort,0)==sort[::-1,:]) + + def test_sort(self): + t = Table(np.array([[0,1,],[2,1,]]), + {'v':(2,)}, + ['test data']) + t.add('s',np.array(['b','a'])) + t.sort_by('s') + assert np.all(t.get('1_v') == np.array([2,0]).reshape((2,1))) diff --git a/python/tests/test_mechanics.py b/python/tests/test_mechanics.py new file mode 100644 index 000000000..aab92bef3 --- /dev/null +++ b/python/tests/test_mechanics.py @@ -0,0 +1,142 @@ +import numpy as np +from damask import mechanics + +class TestMechanics: + + n = 1000 + c = np.random.randint(n) + + + def test_vectorize_Cauchy(self): + P = np.random.random((self.n,3,3)) + F = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.Cauchy(F,P)[self.c], + mechanics.Cauchy(F[self.c],P[self.c])) + + + def test_vectorize_strain_tensor(self): + F = np.random.random((self.n,3,3)) + t = ['V','U'][np.random.randint(0,2)] + m = np.random.random()*10. -5.0 + assert np.allclose(mechanics.strain_tensor(F,t,m)[self.c], + mechanics.strain_tensor(F[self.c],t,m)) + + + def test_vectorize_deviatoric_part(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.deviatoric_part(x)[self.c], + mechanics.deviatoric_part(x[self.c])) + + + def test_vectorize_spherical_part(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.spherical_part(x)[self.c], + mechanics.spherical_part(x[self.c])) + + + def test_vectorize_Mises_stress(self): + sigma = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.Mises_stress(sigma)[self.c], + mechanics.Mises_stress(sigma[self.c])) + + + def test_vectorize_Mises_strain(self): + epsilon = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.Mises_strain(epsilon)[self.c], + mechanics.Mises_strain(epsilon[self.c])) + + + def test_vectorize_symmetric(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.symmetric(x)[self.c], + mechanics.symmetric(x[self.c])) + + + def test_vectorize_maximum_shear(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.maximum_shear(x)[self.c], + mechanics.maximum_shear(x[self.c])) + + + def test_vectorize_principal_components(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.principal_components(x)[self.c], + mechanics.principal_components(x[self.c])) + + + def test_vectorize_transpose(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.transpose(x)[self.c], + mechanics.transpose(x[self.c])) + + + def test_vectorize_rotational_part(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.rotational_part(x)[self.c], + mechanics.rotational_part(x[self.c])) + + + def test_vectorize_left_stretch(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.left_stretch(x)[self.c], + mechanics.left_stretch(x[self.c])) + + + def test_vectorize_right_stretch(self): + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.right_stretch(x)[self.c], + mechanics.right_stretch(x[self.c])) + + + def test_Cauchy(self): + """Ensure Cauchy stress is symmetrized 1. Piola-Kirchhoff stress for no deformation.""" + P = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.Cauchy(np.broadcast_to(np.eye(3),(self.n,3,3)),P), + mechanics.symmetric(P)) + + + def test_strain_tensor_no_rotation(self): + """Ensure that left and right stretch give same results for no rotation.""" + F = np.broadcast_to(np.eye(3),[self.n,3,3])*np.random.random((self.n,3,3)) + m = np.random.random()*20.0-10.0 + assert np.allclose(mechanics.strain_tensor(F,'U',m), + mechanics.strain_tensor(F,'V',m)) + + + def test_strain_tensor_rotation(self): + """Ensure that pure rotation results in no strain.""" + F = mechanics.rotational_part(np.random.random((self.n,3,3))) + t = ['V','U'][np.random.randint(0,2)] + m = np.random.random()*2.0 - 1.0 + assert np.allclose(mechanics.strain_tensor(F,t,m), + 0.0) + + + def test_spherical_deviatoric_part(self): + """Ensure that full tensor is sum of spherical and deviatoric part.""" + x = np.random.random((self.n,3,3)) + sph = np.broadcast_to(np.eye(3),(self.n,3,3))\ + * np.repeat(mechanics.spherical_part(x),9).reshape(self.n,3,3) + assert np.allclose(sph + mechanics.deviatoric_part(x), + x) + + + def test_symmetric(self): + """Ensure that a symmetric tensor is half of the sum of a tensor and its transpose.""" + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.symmetric(x)*2.0, + mechanics.transpose(x)+x) + + + def test_transpose(self): + """Ensure that a symmetric tensor equals its transpose.""" + x = mechanics.symmetric(np.random.random((self.n,3,3))) + assert np.allclose(mechanics.transpose(x), + x) + + + def test_Mises(self): + """Ensure that equivalent stress is 3/2 of equivalent strain.""" + x = np.random.random((self.n,3,3)) + assert np.allclose(mechanics.Mises_stress(x)/mechanics.Mises_strain(x), + 1.5) diff --git a/src/CPFEM.f90 b/src/CPFEM.f90 index 32098b109..9bf8c547c 100644 --- a/src/CPFEM.f90 +++ b/src/CPFEM.f90 @@ -178,19 +178,19 @@ subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt if (iand(mode, CPFEM_RESTOREJACOBIAN) /= 0_pInt) & CPFEM_dcsde = CPFEM_dcsde_knownGood - !*** age results and write restart data if requested + !*** age results if (iand(mode, CPFEM_AGERESULTS) /= 0_pInt) then - crystallite_F0 = crystallite_partionedF ! crystallite deformation (_subF is perturbed...) + crystallite_F0 = crystallite_partionedF ! crystallite deformation crystallite_Fp0 = crystallite_Fp ! crystallite plastic deformation crystallite_Lp0 = crystallite_Lp ! crystallite plastic velocity crystallite_Fi0 = crystallite_Fi ! crystallite intermediate deformation crystallite_Li0 = crystallite_Li ! crystallite intermediate velocity crystallite_S0 = crystallite_S ! crystallite 2nd Piola Kirchhoff stress - forall ( i = 1:size(plasticState )) plasticState(i)%state0 = plasticState(i)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array + forall (i = 1:size(plasticState)) plasticState(i)%state0 = plasticState(i)%state do i = 1, size(sourceState) do mySource = 1,phase_Nsources(i) - sourceState(i)%p(mySource)%state0 = sourceState(i)%p(mySource)%state ! copy state in this lenghty way because: A component cannot be an array if the encompassing structure is an array + sourceState(i)%p(mySource)%state0 = sourceState(i)%p(mySource)%state enddo; enddo if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0_pInt) then write(6,'(a)') '<< CPFEM >> aging states' @@ -275,7 +275,6 @@ subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt if (iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) & write(6,'(a,i8,1x,i2)') '<< CPFEM >> calculation for elFE ip ',elFE,ip call materialpoint_stressAndItsTangent(updateJaco, dt) ! calculate stress and its tangent - call materialpoint_postResults() !* parallel computation and calulation not yet done @@ -284,7 +283,6 @@ subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt write(6,'(a,i8,a,i8)') '<< CPFEM >> calculation for elements ',FEsolving_execElem(1),& ' to ',FEsolving_execElem(2) call materialpoint_stressAndItsTangent(updateJaco, dt) ! calculate stress and its tangent (parallel execution inside) - call materialpoint_postResults() CPFEM_calc_done = .true. endif diff --git a/src/CPFEM2.f90 b/src/CPFEM2.f90 index 7e7949ec8..7123602f8 100644 --- a/src/CPFEM2.f90 +++ b/src/CPFEM2.f90 @@ -11,7 +11,6 @@ module CPFEM2 use FEsolving use math use rotations - use mesh use material use lattice use IO @@ -25,15 +24,19 @@ module CPFEM2 use crystallite #ifdef FEM use FEM_Zoo + use mesh +#else + use mesh_grid #endif implicit none private public :: & - CPFEM_age, & + CPFEM_forward, & CPFEM_initAll, & - CPFEM_results + CPFEM_results, & + CPFEM_restartWrite contains @@ -54,10 +57,10 @@ subroutine CPFEM_initAll call config_init call math_init call rotations_init - call mesh_init call lattice_init call HDF5_utilities_init call results_init + call mesh_init call material_init call constitutive_init call crystallite_init @@ -90,24 +93,24 @@ subroutine CPFEM_init fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5') - call HDF5_read(fileHandle,crystallite_F0, 'convergedF') - call HDF5_read(fileHandle,crystallite_Fp0,'convergedFp') - call HDF5_read(fileHandle,crystallite_Fi0,'convergedFi') - call HDF5_read(fileHandle,crystallite_Lp0,'convergedLp') - call HDF5_read(fileHandle,crystallite_Li0,'convergedLi') - call HDF5_read(fileHandle,crystallite_S0, 'convergedS') + call HDF5_read(fileHandle,crystallite_F0, 'F') + call HDF5_read(fileHandle,crystallite_Fp0,'Fp') + call HDF5_read(fileHandle,crystallite_Fi0,'Fi') + call HDF5_read(fileHandle,crystallite_Lp0,'Lp') + call HDF5_read(fileHandle,crystallite_Li0,'Li') + call HDF5_read(fileHandle,crystallite_S0, 'S') - groupPlasticID = HDF5_openGroup(fileHandle,'PlasticPhases') + groupPlasticID = HDF5_openGroup(fileHandle,'constituent') do ph = 1,size(phase_plasticity) write(PlasticItem,*) ph,'_' - call HDF5_read(groupPlasticID,plasticState(ph)%state0,trim(PlasticItem)//'convergedStateConst') + call HDF5_read(groupPlasticID,plasticState(ph)%state0,trim(PlasticItem)//'omega_plastic') enddo call HDF5_closeGroup(groupPlasticID) - groupHomogID = HDF5_openGroup(fileHandle,'HomogStates') + groupHomogID = HDF5_openGroup(fileHandle,'materialpoint') do homog = 1, material_Nhomogenization write(HomogItem,*) homog,'_' - call HDF5_read(groupHomogID,homogState(homog)%state0, trim(HomogItem)//'convergedStateHomog') + call HDF5_read(groupHomogID,homogState(homog)%state0, trim(HomogItem)//'omega_homogenization') enddo call HDF5_closeGroup(groupHomogID) @@ -118,13 +121,12 @@ end subroutine CPFEM_init !-------------------------------------------------------------------------------------------------- -!> @brief forwards data after successful increment +!> @brief Forward data after successful increment. +! ToDo: Any guessing for the current states possible? !-------------------------------------------------------------------------------------------------- -subroutine CPFEM_age - - integer :: i, ph, homog, mySource - character(len=32) :: rankStr, PlasticItem, HomogItem - integer(HID_T) :: fileHandle, groupPlastic, groupHomog +subroutine CPFEM_forward + + integer :: i, homog, mySource if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0) & write(6,'(a)') '<< CPFEM >> aging states' @@ -149,46 +151,52 @@ subroutine CPFEM_age damageState (homog)%state0 = damageState (homog)%state enddo - if (restartWrite) then - if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0) & - write(6,'(a)') '<< CPFEM >> writing restart variables of last converged step to hdf5 file' - - write(rankStr,'(a1,i0)')'_',worldrank - fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5','a') - - call HDF5_write(fileHandle,crystallite_F0, 'convergedF') - call HDF5_write(fileHandle,crystallite_Fp0, 'convergedFp') - call HDF5_write(fileHandle,crystallite_Fi0, 'convergedFi') - call HDF5_write(fileHandle,crystallite_Lp0, 'convergedLp') - call HDF5_write(fileHandle,crystallite_Li0, 'convergedLi') - call HDF5_write(fileHandle,crystallite_S0, 'convergedS') - - groupPlastic = HDF5_addGroup(fileHandle,'PlasticPhases') - do ph = 1,size(phase_plasticity) - write(PlasticItem,*) ph,'_' - call HDF5_write(groupPlastic,plasticState(ph)%state0,trim(PlasticItem)//'convergedStateConst') - enddo - call HDF5_closeGroup(groupPlastic) - - groupHomog = HDF5_addGroup(fileHandle,'HomogStates') - do homog = 1, material_Nhomogenization - write(HomogItem,*) homog,'_' - call HDF5_write(groupHomog,homogState(homog)%state0,trim(HomogItem)//'convergedStateHomog') - enddo - call HDF5_closeGroup(groupHomog) - - call HDF5_closeFile(fileHandle) - restartWrite = .false. - endif - - if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0) & - write(6,'(a)') '<< CPFEM >> done aging states' - -end subroutine CPFEM_age +end subroutine CPFEM_forward !-------------------------------------------------------------------------------------------------- -!> @brief triggers writing of the results +!> @brief Write current constitutive variables for restart to file. +!-------------------------------------------------------------------------------------------------- +subroutine CPFEM_restartWrite + + integer :: ph, homog + character(len=32) :: rankStr, PlasticItem, HomogItem + integer(HID_T) :: fileHandle, groupPlastic, groupHomog + + + write(6,'(a)') ' writing constitutive data required for restart to file';flush(6) + + write(rankStr,'(a1,i0)')'_',worldrank + fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5','a') + + call HDF5_write(fileHandle,crystallite_partionedF,'F') + call HDF5_write(fileHandle,crystallite_Fp, 'Fp') + call HDF5_write(fileHandle,crystallite_Fi, 'Fi') + call HDF5_write(fileHandle,crystallite_Lp, 'Lp') + call HDF5_write(fileHandle,crystallite_Li, 'Li') + call HDF5_write(fileHandle,crystallite_S, 'S') + + groupPlastic = HDF5_addGroup(fileHandle,'constituent') + do ph = 1,size(phase_plasticity) + write(PlasticItem,*) ph,'_' + call HDF5_write(groupPlastic,plasticState(ph)%state,trim(PlasticItem)//'omega_plastic') + enddo + call HDF5_closeGroup(groupPlastic) + + groupHomog = HDF5_addGroup(fileHandle,'materialpoint') + do homog = 1, material_Nhomogenization + write(HomogItem,*) homog,'_' + call HDF5_write(groupHomog,homogState(homog)%state,trim(HomogItem)//'omega_homogenization') + enddo + call HDF5_closeGroup(groupHomog) + + call HDF5_closeFile(fileHandle) + +end subroutine CPFEM_restartWrite + + +!-------------------------------------------------------------------------------------------------- +!> @brief Trigger writing of results. !-------------------------------------------------------------------------------------------------- subroutine CPFEM_results(inc,time) diff --git a/src/DAMASK_abaqus.f b/src/DAMASK_abaqus.f index 7a43f688e..e2c56a06e 100644 --- a/src/DAMASK_abaqus.f +++ b/src/DAMASK_abaqus.f @@ -21,7 +21,6 @@ module DAMASK_interface implicit none private character(len=4), dimension(2), parameter, public :: INPUTFILEEXTENSION = ['.pes','.inp'] - character(len=4), parameter, public :: LOGFILEEXTENSION = '.log' public :: & DAMASK_interface_init, & diff --git a/src/DAMASK_marc.f90 b/src/DAMASK_marc.f90 index 09a1c83c8..a0a82500f 100644 --- a/src/DAMASK_marc.f90 +++ b/src/DAMASK_marc.f90 @@ -41,8 +41,7 @@ module DAMASK_interface implicit none private - character(len=4), parameter, public :: InputFileExtension = '.dat' - character(len=4), parameter, public :: LogFileExtension = '.log' + character(len=4), parameter, public :: INPUTFILEEXTENSION = '.dat' public :: & DAMASK_interface_init, & @@ -363,37 +362,3 @@ subroutine uedinc(inc,incsub) call CPFEM_results(inc,cptim) end subroutine uedinc - - -!-------------------------------------------------------------------------------------------------- -!> @brief sets user defined output variables for Marc -!> @details select a variable contour plotting (user subroutine). -!-------------------------------------------------------------------------------------------------- -subroutine plotv(v,s,sp,etot,eplas,ecreep,t,m,nn,layer,ndi,nshear,jpltcd) - use prec - use mesh - use IO - use homogenization - - implicit none - integer, intent(in) :: & - m, & !< element number - nn, & !< integration point number - layer, & !< layer number - ndi, & !< number of direct stress components - nshear, & !< number of shear stress components - jpltcd !< user variable index - real(pReal), dimension(*), intent(in) :: & - s, & !< stress array - sp, & !< stresses in preferred direction - etot, & !< total strain (generalized) - eplas, & !< total plastic strain - ecreep, & !< total creep strain - t !< current temperature - real(pReal), intent(out) :: & - v !< variable - - if (jpltcd > materialpoint_sizeResults) call IO_error(700,jpltcd) ! complain about out of bounds error - v = materialpoint_results(jpltcd,nn,mesh_FEasCP('elem', m)) - -end subroutine plotv diff --git a/src/FEsolving.f90 b/src/FEsolving.f90 index 63026b3a6..38788a065 100644 --- a/src/FEsolving.f90 +++ b/src/FEsolving.f90 @@ -5,18 +5,13 @@ !-------------------------------------------------------------------------------------------------- module FEsolving use prec - use debug use IO use DAMASK_interface implicit none private - logical, public :: & -#if defined(Marc4DAMASK) || defined(Abaqus) - restartRead = .false., & !< restart information to continue calculation from saved state -#endif - restartWrite = .false., & !< write current state to enable restart + logical, public :: & terminallyIll = .false. !< at least one material point is terminally ill integer, dimension(:,:), allocatable, public :: & @@ -26,9 +21,7 @@ module FEsolving #if defined(Marc4DAMASK) || defined(Abaqus) logical, public, protected :: & - symmetricSolver = .false. !< use a symmetric FEM solver (only Abaqus) - character(len=1024), public :: & - modelName !< needs description + symmetricSolver = .false. !< use a symmetric FEM solver logical, dimension(:,:), allocatable, public :: & calcMode !< do calculation or simply collect when using ping pong scheme @@ -37,90 +30,36 @@ module FEsolving contains - #if defined(Marc4DAMASK) || defined(Abaqus) !-------------------------------------------------------------------------------------------------- -!> @brief determine whether a symmetric solver is used and whether restart is requested -!> @details restart information is found in input file in case of FEM solvers, in case of spectal -!> solver the information is provided by the interface module +!> @brief determine whether a symmetric solver is used !-------------------------------------------------------------------------------------------------- subroutine FE_init - - integer, parameter :: & - FILEUNIT = 222 - integer :: j - character(len=65536) :: tag, line - integer, allocatable, dimension(:) :: chunkPos write(6,'(/,a)') ' <<<+- FEsolving init -+>>>' - - modelName = getSolverJobName() - call IO_open_inputFile(FILEUNIT,modelName) - rewind(FILEUNIT) - do - read (FILEUNIT,'(a1024)',END=100) line - chunkPos = IO_stringPos(line) - tag = IO_lc(IO_stringValue(line,chunkPos,1)) ! extract key - select case(tag) - case ('solver') - read (FILEUNIT,'(a1024)',END=100) line ! next line + +#if defined(Marc4DAMASK) + block + integer, parameter :: FILEUNIT = 222 + character(len=pStringLen) :: line + integer, allocatable, dimension(:) :: chunkPos + call IO_open_inputFile(FILEUNIT) + rewind(FILEUNIT) + do + read (FILEUNIT,'(a256)',END=100) line + chunkPos = IO_stringPos(line) + if(IO_lc(IO_stringValue(line,chunkPos,1)) == 'solver') then + read (FILEUNIT,'(a256)',END=100) line ! next line chunkPos = IO_stringPos(line) symmetricSolver = (IO_intValue(line,chunkPos,2) /= 1) - case ('restart') - read (FILEUNIT,'(a1024)',END=100) line ! next line - chunkPos = IO_stringPos(line) - restartWrite = iand(IO_intValue(line,chunkPos,1),1) > 0 - restartRead = iand(IO_intValue(line,chunkPos,1),2) > 0 - case ('*restart') - do j=2,chunkPos(1) - restartWrite = (IO_lc(IO_StringValue(line,chunkPos,j)) == 'write') .or. restartWrite - restartRead = (IO_lc(IO_StringValue(line,chunkPos,j)) == 'read') .or. restartRead - enddo - if(restartWrite) then - do j=2,chunkPos(1) - restartWrite = (IO_lc(IO_StringValue(line,chunkPos,j)) /= 'frequency=0') .and. restartWrite - enddo - endif - end select - enddo - 100 close(FILEUNIT) - - if (restartRead) then -#ifdef Marc4DAMASK - call IO_open_logFile(FILEUNIT) - rewind(FILEUNIT) - do - read (FILEUNIT,'(a1024)',END=200) line - chunkPos = IO_stringPos(line) - if ( IO_lc(IO_stringValue(line,chunkPos,1)) == 'restart' & - .and. IO_lc(IO_stringValue(line,chunkPos,2)) == 'file' & - .and. IO_lc(IO_stringValue(line,chunkPos,3)) == 'job' & - .and. IO_lc(IO_stringValue(line,chunkPos,4)) == 'id' ) & - modelName = IO_StringValue(line,chunkPos,6) - enddo -#else - call IO_open_inputFile(FILEUNIT,modelName) - rewind(FILEUNIT) - do - read (FILEUNIT,'(a1024)',END=200) line - chunkPos = IO_stringPos(line) - if (IO_lc(IO_stringValue(line,chunkPos,1))=='*heading') then - read (FILEUNIT,'(a1024)',END=200) line - chunkPos = IO_stringPos(line) - modelName = IO_StringValue(line,chunkPos,1) endif enddo +100 close(FILEUNIT) + end block #endif - 200 close(FILEUNIT) - endif - - if (iand(debug_level(debug_FEsolving),debug_levelBasic) /= 0) then - write(6,'(a21,l1)') ' restart writing: ', restartWrite - write(6,'(a21,l1)') ' restart reading: ', restartRead - if (restartRead) write(6,'(a,/)') ' restart Job: '//trim(modelName) - endif end subroutine FE_init #endif + end module FEsolving diff --git a/src/IO.f90 b/src/IO.f90 index 5d96e67d2..a585fc7c4 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -37,7 +37,6 @@ module IO #if defined(Marc4DAMASK) || defined(Abaqus) public :: & IO_open_inputFile, & - IO_open_logFile, & IO_countContinuousIntValues, & IO_continuousIntValues, & #if defined(Abaqus) @@ -207,27 +206,26 @@ end function IO_open_binary !-------------------------------------------------------------------------------------------------- !> @brief opens FEM input file for reading located in current working directory to given unit !-------------------------------------------------------------------------------------------------- -subroutine IO_open_inputFile(fileUnit,modelName) +subroutine IO_open_inputFile(fileUnit) integer, intent(in) :: fileUnit !< file unit - character(len=*), intent(in) :: modelName !< model name, in case of restart not solver job name integer :: myStat character(len=1024) :: path #if defined(Abaqus) integer :: fileType - + fileType = 1 ! assume .pes - path = trim(modelName)//inputFileExtension(fileType) ! attempt .pes, if it exists: it should be used + path = trim(getSolverJobName())//inputFileExtension(fileType) ! attempt .pes, if it exists: it should be used open(fileUnit+1,status='old',iostat=myStat,file=path,action='read',position='rewind') if(myStat /= 0) then ! if .pes does not work / exist; use conventional extension, i.e.".inp" fileType = 2 - path = trim(modelName)//inputFileExtension(fileType) + path = trim(getSolverJobName())//inputFileExtension(fileType) open(fileUnit+1,status='old',iostat=myStat,file=path,action='read',position='rewind') endif if (myStat /= 0) call IO_error(100,el=myStat,ext_msg=path) - path = trim(modelName)//inputFileExtension(fileType)//'_assembly' + path = trim(getSolverJobName())//inputFileExtension(fileType)//'_assembly' open(fileUnit,iostat=myStat,file=path) if (myStat /= 0) call IO_error(100,el=myStat,ext_msg=path) if (.not.abaqus_assembleInputFile(fileUnit,fileUnit+1)) call IO_error(103) ! strip comments and concatenate any "include"s @@ -258,10 +256,8 @@ subroutine IO_open_inputFile(fileUnit,modelName) fname = trim(line(9+scan(line(9:),'='):)) inquire(file=fname, exist=fexist) if (.not.(fexist)) then - !$OMP CRITICAL (write2out) - write(6,*)'ERROR: file does not exist error in abaqus_assembleInputFile' - write(6,*)'filename: ', trim(fname) - !$OMP END CRITICAL (write2out) + write(6,*)'ERROR: file does not exist error in abaqus_assembleInputFile' + write(6,*)'filename: ', trim(fname) createSuccess = .false. return endif @@ -285,30 +281,12 @@ subroutine IO_open_inputFile(fileUnit,modelName) end function abaqus_assembleInputFile #elif defined(Marc4DAMASK) - path = trim(modelName)//inputFileExtension + path = trim(getSolverJobName())//inputFileExtension open(fileUnit,status='old',iostat=myStat,file=path) if (myStat /= 0) call IO_error(100,el=myStat,ext_msg=path) #endif end subroutine IO_open_inputFile - - -!-------------------------------------------------------------------------------------------------- -!> @brief opens existing FEM log file for reading to given unit. File is named after solver job -!! name and located in current working directory -!-------------------------------------------------------------------------------------------------- -subroutine IO_open_logFile(fileUnit) - - integer, intent(in) :: fileUnit !< file unit - - integer :: myStat - character(len=1024) :: path - - path = trim(getSolverJobName())//LogFileExtension - open(fileUnit,status='old',iostat=myStat,file=path,action='read',position='rewind') - if (myStat /= 0) call IO_error(100,el=myStat,ext_msg=path) - -end subroutine IO_open_logFile #endif @@ -734,11 +712,6 @@ subroutine IO_error(error_ID,el,ip,g,instance,ext_msg) case (602) msg = 'invalid selection for debug' -!------------------------------------------------------------------------------------------------- -! DAMASK_marc errors - case (700) - msg = 'invalid materialpoint result requested' - !------------------------------------------------------------------------------------------------- ! errors related to the grid solver case (809) diff --git a/src/config.f90 b/src/config.f90 index e66b85d2d..00b473767 100644 --- a/src/config.f90 +++ b/src/config.f90 @@ -85,6 +85,7 @@ subroutine config_init case (trim('crystallite')) call parse_materialConfig(config_name_crystallite,config_crystallite,line,fileContent(i+1:)) if (verbose) write(6,'(a)') ' Crystallite parsed'; flush(6) + deallocate(config_crystallite) case (trim('homogenization')) call parse_materialConfig(config_name_homogenization,config_homogenization,line,fileContent(i+1:)) @@ -102,27 +103,25 @@ subroutine config_init call IO_error(160,ext_msg='') if (.not. allocated(config_microstructure) .or. size(config_microstructure) < 1) & call IO_error(160,ext_msg='') - if (.not. allocated(config_crystallite) .or. size(config_crystallite) < 1) & - call IO_error(160,ext_msg='') if (.not. allocated(config_phase) .or. size(config_phase) < 1) & call IO_error(160,ext_msg='') if (.not. allocated(config_texture) .or. size(config_texture) < 1) & call IO_error(160,ext_msg='') - inquire(file='numerics.config', exist=fileExists) - if (fileExists) then - write(6,'(/,a)') ' reading numerics.config'; flush(6) - fileContent = IO_read_ASCII('numerics.config') - call parse_debugAndNumericsConfig(config_numerics,fileContent) - endif + inquire(file='numerics.config', exist=fileExists) + if (fileExists) then + write(6,'(/,a)') ' reading numerics.config'; flush(6) + fileContent = IO_read_ASCII('numerics.config') + call parse_debugAndNumericsConfig(config_numerics,fileContent) + endif - inquire(file='debug.config', exist=fileExists) - if (fileExists) then - write(6,'(/,a)') ' reading debug.config'; flush(6) - fileContent = IO_read_ASCII('debug.config') - call parse_debugAndNumericsConfig(config_debug,fileContent) - endif + inquire(file='debug.config', exist=fileExists) + if (fileExists) then + write(6,'(/,a)') ' reading debug.config'; flush(6) + fileContent = IO_read_ASCII('debug.config') + call parse_debugAndNumericsConfig(config_debug,fileContent) + endif contains @@ -295,9 +294,6 @@ subroutine config_deallocate(what) case('material.config/microstructure') deallocate(config_microstructure) - case('material.config/crystallite') - deallocate(config_crystallite) - case('material.config/homogenization') deallocate(config_homogenization) diff --git a/src/constitutive.f90 b/src/constitutive.f90 index 77054dda3..4067c026a 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -13,7 +13,6 @@ module constitutive use results use HDF5_utilities use lattice - use mesh use discretization use plastic_none use plastic_isotropic @@ -37,7 +36,6 @@ module constitutive private integer, public, protected :: & - constitutive_plasticity_maxSizePostResults, & constitutive_plasticity_maxSizeDotState, & constitutive_source_maxSizePostResults, & constitutive_source_maxSizeDotState @@ -73,8 +71,7 @@ subroutine constitutive_init integer, dimension(:,:), pointer :: thisSize character(len=64), dimension(:,:), pointer :: thisOutput character(len=32) :: outputName !< name of output, intermediate fix until HDF5 output is ready - logical :: knownPlasticity, knownSource, nonlocalConstitutionPresent - nonlocalConstitutionPresent = .false. + logical :: knownSource !-------------------------------------------------------------------------------------------------- ! initialized plasticity @@ -112,64 +109,11 @@ subroutine constitutive_init call IO_write_jobFile(FILEUNIT,'outputConstitutive') PhaseLoop: do ph = 1,material_Nphase activePhase: if (any(material_phaseAt == ph)) then - ins = phase_plasticityInstance(ph) - knownPlasticity = .true. ! assume valid - plasticityType: select case(phase_plasticity(ph)) - case (PLASTICITY_NONE_ID) plasticityType - outputName = PLASTICITY_NONE_label - thisOutput => null() - thisSize => null() - case (PLASTICITY_ISOTROPIC_ID) plasticityType - outputName = PLASTICITY_ISOTROPIC_label - thisOutput => plastic_isotropic_output - thisSize => plastic_isotropic_sizePostResult - case (PLASTICITY_PHENOPOWERLAW_ID) plasticityType - outputName = PLASTICITY_PHENOPOWERLAW_label - thisOutput => plastic_phenopowerlaw_output - thisSize => plastic_phenopowerlaw_sizePostResult - case (PLASTICITY_KINEHARDENING_ID) plasticityType - outputName = PLASTICITY_KINEHARDENING_label - thisOutput => plastic_kinehardening_output - thisSize => plastic_kinehardening_sizePostResult - case (PLASTICITY_DISLOTWIN_ID) plasticityType - outputName = PLASTICITY_DISLOTWIN_label - thisOutput => plastic_dislotwin_output - thisSize => plastic_dislotwin_sizePostResult - case (PLASTICITY_DISLOUCLA_ID) plasticityType - outputName = PLASTICITY_DISLOUCLA_label - thisOutput => plastic_disloucla_output - thisSize => plastic_disloucla_sizePostResult - case (PLASTICITY_NONLOCAL_ID) plasticityType - outputName = PLASTICITY_NONLOCAL_label - thisOutput => plastic_nonlocal_output - thisSize => plastic_nonlocal_sizePostResult - case default plasticityType - knownPlasticity = .false. - end select plasticityType write(FILEUNIT,'(/,a,/)') '['//trim(config_name_phase(ph))//']' - if (knownPlasticity) then - write(FILEUNIT,'(a)') '(plasticity)'//char(9)//trim(outputName) - if (phase_plasticity(ph) /= PLASTICITY_NONE_ID) then - OutputPlasticityLoop: do o = 1,size(thisOutput(:,ins)) - if(len_trim(thisOutput(o,ins)) > 0) & - write(FILEUNIT,'(a,i4)') trim(thisOutput(o,ins))//char(9),thisSize(o,ins) - enddo OutputPlasticityLoop - endif - endif SourceLoop: do s = 1, phase_Nsources(ph) - knownSource = .true. ! assume valid + knownSource = .true. ! assume valid sourceType: select case (phase_source(s,ph)) - case (SOURCE_thermal_dissipation_ID) sourceType - ins = source_thermal_dissipation_instance(ph) - outputName = SOURCE_thermal_dissipation_label - thisOutput => source_thermal_dissipation_output - thisSize => source_thermal_dissipation_sizePostResult - case (SOURCE_thermal_externalheat_ID) sourceType - ins = source_thermal_externalheat_instance(ph) - outputName = SOURCE_thermal_externalheat_label - thisOutput => source_thermal_externalheat_output - thisSize => source_thermal_externalheat_sizePostResult case (SOURCE_damage_isoBrittle_ID) sourceType ins = source_damage_isoBrittle_instance(ph) outputName = SOURCE_damage_isoBrittle_label @@ -207,7 +151,6 @@ subroutine constitutive_init endif mainProcess constitutive_plasticity_maxSizeDotState = 0 - constitutive_plasticity_maxSizePostResults = 0 constitutive_source_maxSizeDotState = 0 constitutive_source_maxSizePostResults = 0 @@ -224,8 +167,6 @@ subroutine constitutive_init ! determine max size of state and output constitutive_plasticity_maxSizeDotState = max(constitutive_plasticity_maxSizeDotState, & plasticState(ph)%sizeDotState) - constitutive_plasticity_maxSizePostResults = max(constitutive_plasticity_maxSizePostResults, & - plasticState(ph)%sizePostResults) constitutive_source_maxSizeDotState = max(constitutive_source_maxSizeDotState, & maxval(sourceState(ph)%p(:)%sizeDotState)) constitutive_source_maxSizePostResults = max(constitutive_source_maxSizePostResults, & @@ -707,61 +648,21 @@ function constitutive_postResults(S, Fi, ipc, ip, el) ipc, & !< component-ID of integration point ip, & !< integration point el !< element - real(pReal), dimension(plasticState(material_phaseAt(ipc,el))%sizePostResults + & - sum(sourceState(material_phaseAt(ipc,el))%p(:)%sizePostResults)) :: & + real(pReal), dimension(sum(sourceState(material_phaseAt(ipc,el))%p(:)%sizePostResults)) :: & constitutive_postResults real(pReal), intent(in), dimension(3,3) :: & Fi !< intermediate deformation gradient real(pReal), intent(in), dimension(3,3) :: & S !< 2nd Piola Kirchhoff stress - real(pReal), dimension(3,3) :: & - Mp !< Mandel stress integer :: & startPos, endPos integer :: & - ho, & !< homogenization - tme, & !< thermal member position i, of, instance !< counter in source loop constitutive_postResults = 0.0_pReal - Mp = matmul(matmul(transpose(Fi),Fi),S) - ho = material_homogenizationAt(el) - tme = thermalMapping(ho)%p(ip,el) - - startPos = 1 - endPos = plasticState(material_phaseAt(ipc,el))%sizePostResults - - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) - - plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el))) - case (PLASTICITY_ISOTROPIC_ID) plasticityType - constitutive_postResults(startPos:endPos) = & - plastic_isotropic_postResults(Mp,instance,of) - - case (PLASTICITY_PHENOPOWERLAW_ID) plasticityType - constitutive_postResults(startPos:endPos) = & - plastic_phenopowerlaw_postResults(Mp,instance,of) - - case (PLASTICITY_KINEHARDENING_ID) plasticityType - constitutive_postResults(startPos:endPos) = & - plastic_kinehardening_postResults(Mp,instance,of) - - case (PLASTICITY_DISLOTWIN_ID) plasticityType - constitutive_postResults(startPos:endPos) = & - plastic_dislotwin_postResults(Mp,temperature(ho)%p(tme),instance,of) - - case (PLASTICITY_DISLOUCLA_ID) plasticityType - constitutive_postResults(startPos:endPos) = & - plastic_disloucla_postResults(Mp,temperature(ho)%p(tme),instance,of) - - case (PLASTICITY_NONLOCAL_ID) plasticityType - constitutive_postResults(startPos:endPos) = & - plastic_nonlocal_postResults (material_phaseAt(ipc,el),instance,of) - - end select plasticityType + endPos = 0 SourceLoop: do i = 1, phase_Nsources(material_phaseAt(ipc,el)) startPos = endPos + 1 diff --git a/src/crystallite.f90 b/src/crystallite.f90 index 26677c26b..292241001 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -16,29 +16,16 @@ module crystallite use numerics use rotations use math - use mesh use FEsolving use material use constitutive use discretization use lattice use plastic_nonlocal - use geometry_plastic_nonlocal, only: & - nIPneighbors => geometry_plastic_nonlocal_nIPneighbors, & - IPneighborhood => geometry_plastic_nonlocal_IPneighborhood - use HDF5_utilities use results implicit none private - character(len=64), dimension(:,:), allocatable :: & - crystallite_output !< name of each post result output - integer, public, protected :: & - crystallite_maxSizePostResults !< description not available - integer, dimension(:), allocatable, public, protected :: & - crystallite_sizePostResults !< description not available - integer, dimension(:,:), allocatable :: & - crystallite_sizePostResult !< description not available real(pReal), dimension(:,:,:), allocatable, public :: & crystallite_dt !< requested time increment of each grain @@ -89,27 +76,6 @@ module crystallite crystallite_todo, & !< flag to indicate need for further computation crystallite_localPlasticity !< indicates this grain to have purely local constitutive law - enum, bind(c) - enumerator :: undefined_ID, & - phase_ID, & - texture_ID, & - orientation_ID, & - grainrotation_ID, & - defgrad_ID, & - fe_ID, & - fp_ID, & - fi_ID, & - lp_ID, & - li_ID, & - p_ID, & - s_ID, & - elasmatrix_ID, & - neighboringip_ID, & - neighboringelement_ID - end enum - integer(kind(undefined_ID)),dimension(:,:), allocatable :: & - crystallite_outputID !< ID of each post result output - type :: tOutput !< new requested output (per phase) character(len=65536), allocatable, dimension(:) :: & label @@ -159,15 +125,10 @@ subroutine crystallite_init c, & !< counter in integration point component loop i, & !< counter in integration point loop e, & !< counter in element loop - o = 0, & !< counter in output loop - r, & cMax, & !< maximum number of integration point components iMax, & !< maximum number of integration points eMax, & !< maximum number of elements - myNcomponents, & !< number of components at current IP - mySize - - character(len=65536), dimension(:), allocatable :: str + myNcomponents !< number of components at current IP write(6,'(/,a)') ' <<<+- crystallite init -+>>>' @@ -214,13 +175,6 @@ subroutine crystallite_init allocate(crystallite_requested(cMax,iMax,eMax), source=.false.) allocate(crystallite_todo(cMax,iMax,eMax), source=.false.) allocate(crystallite_converged(cMax,iMax,eMax), source=.true.) - allocate(crystallite_output(maxval(crystallite_Noutput), & - size(config_crystallite))) ; crystallite_output = '' - allocate(crystallite_outputID(maxval(crystallite_Noutput), & - size(config_crystallite)), source=undefined_ID) - allocate(crystallite_sizePostResults(size(config_crystallite)),source=0) - allocate(crystallite_sizePostResult(maxval(crystallite_Noutput), & - size(config_crystallite)), source=0) num%subStepMinCryst = config_numerics%getFloat('substepmincryst', defaultVal=1.0e-3_pReal) num%subStepSizeCryst = config_numerics%getFloat('substepsizecryst', defaultVal=0.25_pReal) @@ -267,55 +221,6 @@ subroutine crystallite_init integrateState => integrateStateRKCK45 end select - - - do c = 1, size(config_crystallite) -#if defined(__GFORTRAN__) - str = ['GfortranBug86277'] - str = config_crystallite(c)%getStrings('(output)',defaultVal=str) - if (str(1) == 'GfortranBug86277') str = [character(len=65536)::] -#else - str = config_crystallite(c)%getStrings('(output)',defaultVal=[character(len=65536)::]) -#endif - do o = 1, size(str) - crystallite_output(o,c) = str(o) - outputName: select case(str(o)) - case ('phase') outputName - crystallite_outputID(o,c) = phase_ID - case ('texture') outputName - crystallite_outputID(o,c) = texture_ID - case ('orientation') outputName - crystallite_outputID(o,c) = orientation_ID - case ('grainrotation') outputName - crystallite_outputID(o,c) = grainrotation_ID - case ('defgrad','f') outputName ! ToDo: no alias (f only) - crystallite_outputID(o,c) = defgrad_ID - case ('fe') outputName - crystallite_outputID(o,c) = fe_ID - case ('fp') outputName - crystallite_outputID(o,c) = fp_ID - case ('fi') outputName - crystallite_outputID(o,c) = fi_ID - case ('lp') outputName - crystallite_outputID(o,c) = lp_ID - case ('li') outputName - crystallite_outputID(o,c) = li_ID - case ('p','firstpiola','1stpiola') outputName ! ToDo: no alias (p only) - crystallite_outputID(o,c) = p_ID - case ('s','tstar','secondpiola','2ndpiola') outputName ! ToDo: no alias (s only) - crystallite_outputID(o,c) = s_ID - case ('elasmatrix') outputName - crystallite_outputID(o,c) = elasmatrix_ID - case ('neighboringip') outputName ! ToDo: this is not a result, it is static. Should be written out by mesh - crystallite_outputID(o,c) = neighboringip_ID - case ('neighboringelement') outputName ! ToDo: this is not a result, it is static. Should be written out by mesh - crystallite_outputID(o,c) = neighboringelement_ID - case default outputName - call IO_error(105,ext_msg=trim(str(o))//' (Crystallite)') - end select outputName - enddo - enddo - allocate(output_constituent(size(config_phase))) do c = 1, size(config_phase) #if defined(__GFORTRAN__) @@ -328,51 +233,14 @@ subroutine crystallite_init #endif enddo - - do r = 1,size(config_crystallite) - do o = 1,crystallite_Noutput(r) - select case(crystallite_outputID(o,r)) - case(phase_ID,texture_ID) - mySize = 1 - case(orientation_ID,grainrotation_ID) - mySize = 4 - case(defgrad_ID,fe_ID,fp_ID,fi_ID,lp_ID,li_ID,p_ID,s_ID) - mySize = 9 - case(elasmatrix_ID) - mySize = 36 - case(neighboringip_ID,neighboringelement_ID) - mySize = nIPneighbors - case default - mySize = 0 - end select - crystallite_sizePostResult(o,r) = mySize - crystallite_sizePostResults(r) = crystallite_sizePostResults(r) + mySize - enddo - enddo - - crystallite_maxSizePostResults = & - maxval(crystallite_sizePostResults(microstructure_crystallite),microstructure_active) - - !-------------------------------------------------------------------------------------------------- ! write description file for crystallite output if (worldrank == 0) then call IO_write_jobFile(FILEUNIT,'outputCrystallite') - - do r = 1,size(config_crystallite) - if (any(microstructure_crystallite(discretization_microstructureAt) == r)) then - write(FILEUNIT,'(/,a,/)') '['//trim(config_name_crystallite(r))//']' - do o = 1,crystallite_Noutput(r) - write(FILEUNIT,'(a,i4)') trim(crystallite_output(o,r))//char(9),crystallite_sizePostResult(o,r) - enddo - endif - enddo - + write(FILEUNIT,'(/,a,/)') '[not supported anymore]' close(FILEUNIT) endif - call config_deallocate('material.config/phase') - call config_deallocate('material.config/crystallite') !-------------------------------------------------------------------------------------------------- ! initialize @@ -874,96 +742,18 @@ function crystallite_postResults(ipc, ip, el) ip, & !< integration point index ipc !< grain index - real(pReal), dimension(1+crystallite_sizePostResults(microstructure_crystallite(discretization_microstructureAt(el))) + & - 1+plasticState(material_phaseAt(ipc,el))%sizePostResults + & - sum(sourceState(material_phaseAt(ipc,el))%p(:)%sizePostResults)) :: & + real(pReal), dimension(1+ & + 1+sum(sourceState(material_phaseAt(ipc,el))%p(:)%sizePostResults)) :: & crystallite_postResults integer :: & - o, & - c, & - crystID, & - mySize, & - n - type(rotation) :: rot + c - crystID = microstructure_crystallite(discretization_microstructureAt(el)) crystallite_postResults = 0.0_pReal - crystallite_postResults(1) = real(crystallite_sizePostResults(crystID),pReal) ! header-like information (length) + crystallite_postResults(1) = 0.0_pReal ! header-like information (length) c = 1 - do o = 1,crystallite_Noutput(crystID) - mySize = 0 - select case(crystallite_outputID(o,crystID)) - case (phase_ID) - mySize = 1 - crystallite_postResults(c+1) = real(material_phaseAt(ipc,el),pReal) ! phaseID of grain - case (texture_ID) - mySize = 1 - crystallite_postResults(c+1) = real(material_texture(ipc,ip,el),pReal) ! textureID of grain - case (orientation_ID) - mySize = 4 - crystallite_postResults(c+1:c+mySize) = crystallite_orientation(ipc,ip,el)%asQuaternion() - - case (grainrotation_ID) - rot = material_orientation0(ipc,ip,el)%misorientation(crystallite_orientation(ipc,ip,el)) - mySize = 4 - crystallite_postResults(c+1:c+mySize) = rot%asAxisAngle() - crystallite_postResults(c+4) = inDeg * crystallite_postResults(c+4) ! angle in degree - -! remark: tensor output is of the form 11,12,13, 21,22,23, 31,32,33 -! thus row index i is slow, while column index j is fast. reminder: "row is slow" - - case (defgrad_ID) - mySize = 9 - crystallite_postResults(c+1:c+mySize) = & - reshape(transpose(crystallite_partionedF(1:3,1:3,ipc,ip,el)),[mySize]) - case (fe_ID) - mySize = 9 - crystallite_postResults(c+1:c+mySize) = & - reshape(transpose(crystallite_Fe(1:3,1:3,ipc,ip,el)),[mySize]) - case (fp_ID) - mySize = 9 - crystallite_postResults(c+1:c+mySize) = & - reshape(transpose(crystallite_Fp(1:3,1:3,ipc,ip,el)),[mySize]) - case (fi_ID) - mySize = 9 - crystallite_postResults(c+1:c+mySize) = & - reshape(transpose(crystallite_Fi(1:3,1:3,ipc,ip,el)),[mySize]) - case (lp_ID) - mySize = 9 - crystallite_postResults(c+1:c+mySize) = & - reshape(transpose(crystallite_Lp(1:3,1:3,ipc,ip,el)),[mySize]) - case (li_ID) - mySize = 9 - crystallite_postResults(c+1:c+mySize) = & - reshape(transpose(crystallite_Li(1:3,1:3,ipc,ip,el)),[mySize]) - case (p_ID) - mySize = 9 - crystallite_postResults(c+1:c+mySize) = & - reshape(transpose(crystallite_P(1:3,1:3,ipc,ip,el)),[mySize]) - case (s_ID) - mySize = 9 - crystallite_postResults(c+1:c+mySize) = & - reshape(crystallite_S(1:3,1:3,ipc,ip,el),[mySize]) - case (elasmatrix_ID) - mySize = 36 - crystallite_postResults(c+1:c+mySize) = reshape(constitutive_homogenizedC(ipc,ip,el),[mySize]) - case(neighboringelement_ID) - mySize = nIPneighbors - crystallite_postResults(c+1:c+mySize) = 0.0_pReal - forall (n = 1:mySize) & - crystallite_postResults(c+n) = real(IPneighborhood(1,n,ip,el),pReal) - case(neighboringip_ID) - mySize = nIPneighbors - crystallite_postResults(c+1:c+mySize) = 0.0_pReal - forall (n = 1:mySize) & - crystallite_postResults(c+n) = real(IPneighborhood(2,n,ip,el),pReal) - end select - c = c + mySize - enddo - - crystallite_postResults(c+1) = real(plasticState(material_phaseAt(ipc,el))%sizePostResults,pReal) ! size of constitutive results + crystallite_postResults(c+1) = real(sum(sourceState(material_phaseAt(ipc,el))%p(:)%sizePostResults),pReal) ! size of constitutive results c = c + 1 if (size(crystallite_postResults)-c > 0) & crystallite_postResults(c+1:size(crystallite_postResults)) = & @@ -986,7 +776,7 @@ subroutine crystallite_results do p=1,size(config_name_phase) group = trim('current/constituent')//'/'//trim(config_name_phase(p))//'/generic' - call HDF5_closeGroup(results_addGroup(group)) + call results_closeGroup(results_addGroup(group)) do o = 1, size(output_constituent(p)%label) select case (output_constituent(p)%label(o)) @@ -1056,16 +846,16 @@ subroutine crystallite_results real(pReal), allocatable, dimension(:,:,:) :: select_tensors integer :: e,i,c,j - allocate(select_tensors(3,3,count(material_phaseAt==instance)*homogenization_maxNgrains)) + allocate(select_tensors(3,3,count(material_phaseAt==instance)*homogenization_maxNgrains*discretization_nIP)) j=0 do e = 1, size(material_phaseAt,2) - do i = 1, homogenization_maxNgrains !ToDo: this needs to be changed for varying Ngrains - do c = 1, size(material_phaseAt,1) - if (material_phaseAt(c,e) == instance) then - j = j + 1 - select_tensors(1:3,1:3,j) = dataset(1:3,1:3,c,i,e) - endif + do i = 1, discretization_nIP + do c = 1, size(material_phaseAt,1) !ToDo: this needs to be changed for varying Ngrains + if (material_phaseAt(c,e) == instance) then + j = j + 1 + select_tensors(1:3,1:3,j) = dataset(1:3,1:3,c,i,e) + endif enddo enddo enddo @@ -1083,12 +873,12 @@ subroutine crystallite_results type(rotation), allocatable, dimension(:) :: select_rotations integer :: e,i,c,j - allocate(select_rotations(count(material_phaseAt==instance)*homogenization_maxNgrains)) + allocate(select_rotations(count(material_phaseAt==instance)*homogenization_maxNgrains*discretization_nIP)) j=0 do e = 1, size(material_phaseAt,2) - do i = 1, homogenization_maxNgrains !ToDo: this needs to be changed for varying Ngrains - do c = 1, size(material_phaseAt,1) + do i = 1, discretization_nIP + do c = 1, size(material_phaseAt,1) !ToDo: this needs to be changed for varying Ngrains if (material_phaseAt(c,e) == instance) then j = j + 1 select_rotations(j) = dataset(c,i,e) diff --git a/src/damage_none.f90 b/src/damage_none.f90 index 5ffdba030..62d2cc0eb 100644 --- a/src/damage_none.f90 +++ b/src/damage_none.f90 @@ -30,7 +30,6 @@ subroutine damage_none_init myhomog: if (damage_type(homog) == DAMAGE_NONE_ID) then NofMyHomog = count(material_homogenizationAt == homog) damageState(homog)%sizeState = 0 - damageState(homog)%sizePostResults = 0 allocate(damageState(homog)%state0 (0,NofMyHomog)) allocate(damageState(homog)%subState0(0,NofMyHomog)) allocate(damageState(homog)%state (0,NofMyHomog)) diff --git a/src/damage_nonlocal.f90 b/src/damage_nonlocal.f90 index 73056d3c9..0a8a3c867 100644 --- a/src/damage_nonlocal.f90 +++ b/src/damage_nonlocal.f90 @@ -10,7 +10,6 @@ module damage_nonlocal use config use crystallite use lattice - use mesh use source_damage_isoBrittle use source_damage_isoDuctile use source_damage_anisoBrittle diff --git a/src/discretization.f90 b/src/discretization.f90 index 81413e9b8..873148666 100644 --- a/src/discretization.f90 +++ b/src/discretization.f90 @@ -6,9 +6,6 @@ module discretization use prec use results -#if defined(PETSc) || defined(DAMASK_HDF5) - use HDF5_utilities -#endif implicit none private @@ -26,18 +23,24 @@ module discretization discretization_NodeCoords0, & discretization_IPcoords, & discretization_NodeCoords + + integer :: & + discretization_sharedNodesBeginn public :: & discretization_init, & discretization_results, & - discretization_setIPcoords + discretization_setIPcoords, & + discretization_setNodeCoords contains !-------------------------------------------------------------------------------------------------- !> @brief stores the relevant information in globally accesible variables !-------------------------------------------------------------------------------------------------- -subroutine discretization_init(homogenizationAt,microstructureAt,IPcoords0,NodeCoords0) +subroutine discretization_init(homogenizationAt,microstructureAt,& + IPcoords0,NodeCoords0,& + sharedNodesBeginn) integer, dimension(:), intent(in) :: & homogenizationAt, & @@ -45,6 +48,8 @@ subroutine discretization_init(homogenizationAt,microstructureAt,IPcoords0,NodeC real(pReal), dimension(:,:), intent(in) :: & IPcoords0, & NodeCoords0 + integer, optional, intent(in) :: & + sharedNodesBeginn write(6,'(/,a)') ' <<<+- discretization init -+>>>' @@ -60,6 +65,12 @@ subroutine discretization_init(homogenizationAt,microstructureAt,IPcoords0,NodeC discretization_NodeCoords0 = NodeCoords0 discretization_NodeCoords = NodeCoords0 + if(present(sharedNodesBeginn)) then + discretization_sharedNodesBeginn = sharedNodesBeginn + else + discretization_sharedNodesBeginn = size(discretization_NodeCoords0,2) + endif + end subroutine discretization_init @@ -70,12 +81,14 @@ subroutine discretization_results #if defined(PETSc) || defined(DAMASK_HDF5) real(pReal), dimension(:,:), allocatable :: u - call HDF5_closeGroup(results_addGroup(trim('current/geometry'))) + call results_closeGroup(results_addGroup(trim('current/geometry'))) - u = discretization_NodeCoords - discretization_NodeCoords0 + u = discretization_NodeCoords (1:3,:discretization_sharedNodesBeginn) & + - discretization_NodeCoords0(1:3,:discretization_sharedNodesBeginn) call results_writeDataset('current/geometry',u,'u_n','nodal displacements','m') - u = discretization_IPcoords - discretization_IPcoords0 + u = discretization_IPcoords & + - discretization_IPcoords0 call results_writeDataset('current/geometry',u,'u_c','cell center displacements','m') #endif end subroutine discretization_results @@ -92,4 +105,17 @@ subroutine discretization_setIPcoords(IPcoords) end subroutine discretization_setIPcoords + +!-------------------------------------------------------------------------------------------------- +!> @brief stores current IP coordinates +!-------------------------------------------------------------------------------------------------- +subroutine discretization_setNodeCoords(NodeCoords) + + real(pReal), dimension(:,:), intent(in) :: NodeCoords + + discretization_NodeCoords = NodeCoords + +end subroutine discretization_setNodeCoords + + end module discretization diff --git a/src/geometry_plastic_nonlocal.f90 b/src/geometry_plastic_nonlocal.f90 index 88634c245..408306b2b 100644 --- a/src/geometry_plastic_nonlocal.f90 +++ b/src/geometry_plastic_nonlocal.f90 @@ -122,7 +122,7 @@ subroutine geometry_plastic_nonlocal_results integer, dimension(:), allocatable :: shp -#if defined(DAMASK_HDF5) +#if defined(PETSc) || defined(DAMASK_HDF5) call results_openJobFile writeVolume: block diff --git a/src/grid/DAMASK_grid.f90 b/src/grid/DAMASK_grid.f90 index 71d95187b..51c97456b 100644 --- a/src/grid/DAMASK_grid.f90 +++ b/src/grid/DAMASK_grid.f90 @@ -15,7 +15,7 @@ program DAMASK_spectral use config use debug use math - use mesh + use mesh_grid use CPFEM2 use FEsolving use numerics @@ -27,9 +27,7 @@ program DAMASK_spectral use grid_mech_FEM use grid_damage_spectral use grid_thermal_spectral - use HDF5_utilities use results - use rotations implicit none @@ -60,7 +58,8 @@ program DAMASK_spectral remainingLoadCaseTime = 0.0_pReal !< remaining time of current load case logical :: & guess, & !< guess along former trajectory - stagIterate + stagIterate, & + cutBack = .false. integer :: & i, j, k, l, field, & errorID = 0, & @@ -70,23 +69,20 @@ program DAMASK_spectral currentLoadcase = 0, & !< current load case inc, & !< current increment in current load case totalIncsCounter = 0, & !< total # of increments - convergedCounter = 0, & !< # of converged increments - notConvergedCounter = 0, & !< # of non-converged increments fileUnit = 0, & !< file unit for reading load case and writing results myStat, & statUnit = 0, & !< file unit for statistics output - lastRestartWritten = 0, & !< total increment # at which last restart information was written - stagIter + stagIter, & + nActiveFields = 0 character(len=6) :: loadcase_string character(len=1024) :: & incInfo - type(rotation) :: R type(tLoadCase), allocatable, dimension(:) :: loadCases !< array of all load cases type(tLoadCase) :: newLoadCase type(tSolutionState), allocatable, dimension(:) :: solres integer(MPI_OFFSET_KIND) :: fileOffset integer(MPI_OFFSET_KIND), dimension(:), allocatable :: outputSize - integer, parameter :: maxByteOut = 2147483647-4096 !< limit of one file output write https://trac.mpich.org/projects/mpich/ticket/1742 + integer, parameter :: maxByteOut = 2147483647-4096 !< limit of one file output write https://trac.mpich.org/projects/mpich/ticket/1742 integer, parameter :: maxRealOut = maxByteOut/pReal integer(pLongInt), dimension(2) :: outputIndex PetscErrorCode :: ierr @@ -96,6 +92,10 @@ program DAMASK_spectral 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 external :: & quit @@ -120,23 +120,29 @@ program DAMASK_spectral ! assign mechanics solver depending on selected type select case (trim(config_numerics%getString('spectral_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_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 case ('polarisation') if(iand(debug_level(debug_spectral),debug_levelBasic)/= 0) & call IO_warning(42, ext_msg='debug Divergence') - mech_init => grid_mech_spectral_polarisation_init - mech_forward => grid_mech_spectral_polarisation_forward - mech_solution => grid_mech_spectral_polarisation_solution - + 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 ('fem') if(iand(debug_level(debug_spectral),debug_levelBasic)/= 0) & call IO_warning(42, ext_msg='debug Divergence') - mech_init => grid_mech_FEM_init - mech_forward => grid_mech_FEM_forward - mech_solution => grid_mech_FEM_solution + 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 case default call IO_error(error_ID = 891, ext_msg = config_numerics%getString('spectral_solver')) @@ -158,11 +164,11 @@ program DAMASK_spectral chunkPos = IO_stringPos(line) do i = 1, chunkPos(1) ! reading compulsory parameters for loadcase select case (IO_lc(IO_stringValue(line,chunkPos,i))) - case('l','velocitygrad','velgrad','velocitygradient','fdot','dotf','f') + case('l','fdot','dotf','f') N_def = N_def + 1 case('t','time','delta') N_t = N_t + 1 - case('n','incs','increments','steps','logincs','logincrements','logsteps') + case('n','incs','increments','logincs','logincrements') N_n = N_n + 1 end select enddo @@ -181,9 +187,10 @@ program DAMASK_spectral newLoadCase%ID(field) = FIELD_DAMAGE_ID endif damageActive + call newLoadCase%rot%fromEulers(real([0.0,0.0,0.0],pReal)) readIn: do i = 1, chunkPos(1) select case (IO_lc(IO_stringValue(line,chunkPos,i))) - case('fdot','dotf','l','velocitygrad','velgrad','velocitygradient','f') ! assign values for the deformation BC matrix + case('fdot','dotf','l','f') ! assign values for the deformation BC matrix temp_valueVector = 0.0_pReal if (IO_lc(IO_stringValue(line,chunkPos,i)) == 'fdot'.or. & ! in case of Fdot, set type to fdot IO_lc(IO_stringValue(line,chunkPos,i)) == 'dotf') then @@ -200,7 +207,7 @@ program DAMASK_spectral newLoadCase%deformation%maskLogical = transpose(reshape(temp_maskVector,[ 3,3])) ! logical mask in 3x3 notation newLoadCase%deformation%maskFloat = merge(ones,zeros,newLoadCase%deformation%maskLogical)! float (1.0/0.0) mask in 3x3 notation newLoadCase%deformation%values = math_9to33(temp_valueVector) ! values in 3x3 notation - case('p','pk1','piolakirchhoff','stress', 's') + case('p','stress', 's') temp_valueVector = 0.0_pReal do j = 1, 9 temp_maskVector(j) = IO_stringValue(line,chunkPos,i+j) /= '*' ! true if not an asterisk @@ -211,9 +218,9 @@ program DAMASK_spectral newLoadCase%stress%values = math_9to33(temp_valueVector) case('t','time','delta') ! increment time newLoadCase%time = IO_floatValue(line,chunkPos,i+1) - case('n','incs','increments','steps') ! number of increments + case('n','incs','increments') ! number of increments newLoadCase%incs = IO_intValue(line,chunkPos,i+1) - case('logincs','logincrements','logsteps') ! number of increments (switch to log time scaling) + case('logincs','logincrements') ! number of increments (switch to log time scaling) newLoadCase%incs = IO_intValue(line,chunkPos,i+1) newLoadCase%logscale = 1 case('freq','frequency','outputfreq') ! frequency of result writings @@ -236,14 +243,13 @@ program DAMASK_spectral do j = 1, 3 temp_valueVector(j) = IO_floatValue(line,chunkPos,i+k+j) enddo - call R%fromEulers(temp_valueVector(1:3),degrees=(l==1)) - newLoadCase%rotation = R%asMatrix() + call newLoadCase%rot%fromEulers(temp_valueVector(1:3),degrees=(l==1)) case('rotation','rot') ! assign values for the rotation matrix temp_valueVector = 0.0_pReal do j = 1, 9 temp_valueVector(j) = IO_floatValue(line,chunkPos,i+j) enddo - newLoadCase%rotation = math_9to33(temp_valueVector) + call newLoadCase%rot%fromMatrix(math_9to33(temp_valueVector)) end select enddo readIn @@ -287,14 +293,12 @@ program DAMASK_spectral endif enddo; write(6,'(/)',advance='no') enddo - if (any(abs(matmul(newLoadCase%rotation, & - transpose(newLoadCase%rotation))-math_I3) > & - reshape(spread(tol_math_check,1,9),[ 3,3]))& - .or. abs(math_det33(newLoadCase%rotation)) > & - 1.0_pReal + tol_math_check) errorID = 846 ! given rotation matrix contains strain - if (any(dNeq(newLoadCase%rotation, math_I3))) & + if (any(abs(matmul(newLoadCase%rot%asMatrix(), & + transpose(newLoadCase%rot%asMatrix()))-math_I3) > & + reshape(spread(tol_math_check,1,9),[ 3,3]))) errorID = 846 ! given rotation matrix contains strain + if (any(dNeq(newLoadCase%rot%asMatrix(), math_I3))) & write(6,'(2x,a,/,3(3(3x,f12.7,1x)/))',advance='no') 'rotation of loadframe:',& - transpose(newLoadCase%rotation) + transpose(newLoadCase%rot%asMatrix()) if (newLoadCase%time < 0.0_pReal) errorID = 834 ! negative time increment write(6,'(2x,a,f12.6)') 'time: ', newLoadCase%time if (newLoadCase%incs < 1) errorID = 835 ! non-positive incs count @@ -310,15 +314,9 @@ program DAMASK_spectral enddo close(fileUnit) - call results_openJobFile - call HDF5_closeGroup(results_addGroup('geometry')) - call results_addAttribute('grid',grid,'geometry') - call results_addAttribute('size',geomSize,'geometry') - call results_closeJobFile - !-------------------------------------------------------------------------------------------------- ! doing initialization depending on active solvers - call Utilities_init() + call Utilities_init do field = 1, nActiveFields select case (loadCases(1)%ID(field)) case(FIELD_MECH_ID) @@ -464,15 +462,16 @@ program DAMASK_spectral select case(loadCases(currentLoadCase)%ID(field)) case(FIELD_MECH_ID) call mech_forward (& - guess,timeinc,timeIncOld,remainingLoadCaseTime, & + cutBack,guess,timeinc,timeIncOld,remainingLoadCaseTime, & deformation_BC = loadCases(currentLoadCase)%deformation, & stress_BC = loadCases(currentLoadCase)%stress, & - rotation_BC = loadCases(currentLoadCase)%rotation) + rotation_BC = loadCases(currentLoadCase)%rot) - case(FIELD_THERMAL_ID); call grid_thermal_spectral_forward - case(FIELD_DAMAGE_ID); call grid_damage_spectral_forward + case(FIELD_THERMAL_ID); call grid_thermal_spectral_forward(cutBack) + case(FIELD_DAMAGE_ID); call grid_damage_spectral_forward(cutBack) end select enddo + if(.not. cutBack) call CPFEM_forward !-------------------------------------------------------------------------------------------------- ! solve fields @@ -485,7 +484,7 @@ program DAMASK_spectral solres(field) = mech_solution (& incInfo,timeinc,timeIncOld, & stress_BC = loadCases(currentLoadCase)%stress, & - rotation_BC = loadCases(currentLoadCase)%rotation) + rotation_BC = loadCases(currentLoadCase)%rot) case(FIELD_THERMAL_ID) solres(field) = grid_thermal_spectral_solution(timeinc,timeIncOld) @@ -507,8 +506,9 @@ program DAMASK_spectral !-------------------------------------------------------------------------------------------------- ! check solution for either advance or retry - if ( (continueCalculation .or. all(solres(:)%converged .and. solres(:)%stagConverged)) & ! don't care or did converge + if ( (all(solres(:)%converged .and. solres(:)%stagConverged)) & ! converged .and. .not. solres(1)%termIll) then ! and acceptable solution found + call mech_updateCoords timeIncOld = timeinc cutBack = .false. guess = .true. ! start guessing after first converged (sub)inc @@ -528,7 +528,7 @@ program DAMASK_spectral call IO_warning(850) call MPI_File_close(fileUnit,ierr) close(statUnit) - call quit(-1*(lastRestartWritten+1)) ! quit and provide information about last restart inc written + call quit(0) ! quit endif enddo subStepLooping @@ -536,11 +536,9 @@ program DAMASK_spectral cutBackLevel = max(0, cutBackLevel - 1) ! try half number of subincs next inc if (all(solres(:)%converged)) then - convergedCounter = convergedCounter + 1 write(6,'(/,a,'//IO_intOut(totalIncsCounter)//',a)') & ! report converged inc ' increment ', totalIncsCounter, ' converged' else - notConvergedCounter = notConvergedCounter + 1 write(6,'(/,a,'//IO_intOut(totalIncsCounter)//',a)') & ! report non-converged inc ' increment ', totalIncsCounter, ' NOT converged' endif; flush(6) @@ -563,11 +561,10 @@ program DAMASK_spectral fileOffset = fileOffset + sum(outputSize) ! forward to current file position call CPFEM_results(totalIncsCounter,time) endif - if (mod(inc,loadCases(currentLoadCase)%restartFrequency) == 0) then ! at frequency of writing restart information - restartWrite = .true. ! set restart parameter for FEsolving - lastRestartWritten = inc ! QUESTION: first call to CPFEM_general will write? + if (mod(inc,loadCases(currentLoadCase)%restartFrequency) == 0) then + call mech_restartWrite + call CPFEM_restartWrite endif - endif skipping enddo incLooping @@ -578,16 +575,9 @@ program DAMASK_spectral !-------------------------------------------------------------------------------------------------- ! report summary of whole calculation write(6,'(/,a)') ' ###########################################################################' - write(6,'(1x,'//IO_intOut(convergedCounter)//',a,'//IO_intOut(notConvergedCounter + convergedCounter)//',a,f5.1,a)') & - convergedCounter, ' out of ', & - notConvergedCounter + convergedCounter, ' (', & - real(convergedCounter, pReal)/& - real(notConvergedCounter + convergedCounter,pReal)*100.0_pReal, ' %) increments converged!' - flush(6) call MPI_file_close(fileUnit,ierr) close(statUnit) - if (notConvergedCounter > 0) call quit(2) ! error if some are not converged call quit(0) ! no complains ;) end program DAMASK_spectral diff --git a/src/grid/grid_damage_spectral.f90 b/src/grid/grid_damage_spectral.f90 index bdd9a6b89..1fb91b49b 100644 --- a/src/grid/grid_damage_spectral.f90 +++ b/src/grid/grid_damage_spectral.f90 @@ -12,7 +12,7 @@ module grid_damage_spectral use prec use spectral_utilities - use mesh + use mesh_grid use damage_nonlocal use numerics use damage_nonlocal @@ -203,8 +203,9 @@ end function grid_damage_spectral_solution !-------------------------------------------------------------------------------------------------- !> @brief spectral damage forwarding routine !-------------------------------------------------------------------------------------------------- -subroutine grid_damage_spectral_forward +subroutine grid_damage_spectral_forward(cutBack) + logical, intent(in) :: cutBack integer :: i, j, k, cell DM :: dm_local PetscScalar, dimension(:,:,:), pointer :: x_scal diff --git a/src/grid/grid_mech_FEM.f90 b/src/grid/grid_mech_FEM.f90 index 59252a674..e87e02d09 100644 --- a/src/grid/grid_mech_FEM.f90 +++ b/src/grid/grid_mech_FEM.f90 @@ -21,7 +21,7 @@ module grid_mech_FEM use DAMASK_interface use spectral_utilities use discretization - use mesh + use mesh_grid use math implicit none @@ -71,7 +71,9 @@ module grid_mech_FEM public :: & grid_mech_FEM_init, & grid_mech_FEM_solution, & - grid_mech_FEM_forward + grid_mech_FEM_forward, & + grid_mech_FEM_updateCoords, & + grid_mech_FEM_restartWrite contains @@ -95,7 +97,7 @@ subroutine grid_mech_FEM_init 1.0_pReal, 1.0_pReal, 1.0_pReal, 1.0_pReal], [4,8]) PetscErrorCode :: ierr integer :: rank - integer(HID_T) :: fileHandle + integer(HID_T) :: fileHandle, groupHandle character(len=1024) :: rankStr real(pReal), dimension(3,3,3,3) :: devNull PetscScalar, pointer, dimension(:,:,:,:) :: & @@ -186,26 +188,26 @@ subroutine grid_mech_FEM_init 'reading values of increment ', interface_restartInc, ' from file' write(rankStr,'(a1,i0)')'_',worldrank - fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5') + fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5') + groupHandle = HDF5_openGroup(fileHandle,'solver') - call HDF5_read(fileHandle,F_aim, 'F_aim') - call HDF5_read(fileHandle,F_aim_lastInc,'F_aim_lastInc') - call HDF5_read(fileHandle,F_aimDot, 'F_aimDot') - call HDF5_read(fileHandle,F, 'F') - call HDF5_read(fileHandle,F_lastInc, 'F_lastInc') - call HDF5_read(fileHandle,u_current, 'u') - call HDF5_read(fileHandle,u_lastInc, 'u_lastInc') + call HDF5_read(groupHandle,F_aim, 'F_aim') + call HDF5_read(groupHandle,F_aim_lastInc,'F_aim_lastInc') + call HDF5_read(groupHandle,F_aimDot, 'F_aimDot') + call HDF5_read(groupHandle,F, 'F') + call HDF5_read(groupHandle,F_lastInc, 'F_lastInc') + call HDF5_read(groupHandle,u_current, 'u') + call HDF5_read(groupHandle,u_lastInc, 'u_lastInc') elseif (interface_restartInc == 0) then restartRead F_lastInc = spread(spread(spread(math_I3,3,grid(1)),4,grid(2)),5,grid3) ! initialize to identity F = spread(spread(spread(math_I3,3,grid(1)),4,grid(2)),5,grid3) endif restartRead materialpoint_F0 = reshape(F_lastInc, [3,3,1,product(grid(1:2))*grid3]) ! set starting condition for materialpoint_stressAndItsTangent - call utilities_updateIPcoords(F) + call utilities_updateCoords(F) call utilities_constitutiveResponse(P_current,temp33_Real,C_volAvg,devNull, & ! stress field, stress avg, global average of stiffness and (min+max)/2 F, & ! target F - 0.0_pReal, & ! time increment - math_I3) ! no rotation of boundary condition + 0.0_pReal) ! time increment call DMDAVecRestoreArrayF90(mech_grid,solution_current,u_current,ierr) CHKERRQ(ierr) call DMDAVecRestoreArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr) @@ -214,9 +216,12 @@ subroutine grid_mech_FEM_init restartRead2: if (interface_restartInc > 0) then write(6,'(/,a,'//IO_intOut(interface_restartInc)//',a)') & 'reading more values of increment ', interface_restartInc, ' from file' - call HDF5_read(fileHandle,C_volAvg, 'C_volAvg') - call HDF5_read(fileHandle,C_volAvgLastInc,'C_volAvgLastInc') + call HDF5_read(groupHandle,C_volAvg, 'C_volAvg') + call HDF5_read(groupHandle,C_volAvgLastInc,'C_volAvgLastInc') + + call HDF5_closeGroup(groupHandle) call HDF5_closeFile(fileHandle) + endif restartRead2 end subroutine grid_mech_FEM_init @@ -236,7 +241,8 @@ function grid_mech_FEM_solution(incInfoIn,timeinc,timeinc_old,stress_BC,rotation timeinc_old !< time increment of last successful increment type(tBoundaryCondition), intent(in) :: & stress_BC - real(pReal), dimension(3,3), intent(in) :: rotation_BC + type(rotation), intent(in) :: & + rotation_BC type(tSolutionState) :: & solution !-------------------------------------------------------------------------------------------------- @@ -278,9 +284,11 @@ end function grid_mech_FEM_solution !> @details find new boundary conditions and best F estimate for end of current timestep !> possibly writing restart information, triggering of state increment in DAMASK, and updating of IPcoordinates !-------------------------------------------------------------------------------------------------- -subroutine grid_mech_FEM_forward(guess,timeinc,timeinc_old,loadCaseTime,deformation_BC,stress_BC,rotation_BC) +subroutine grid_mech_FEM_forward(cutBack,guess,timeinc,timeinc_old,loadCaseTime,& + deformation_BC,stress_BC,rotation_BC) logical, intent(in) :: & + cutBack, & guess real(pReal), intent(in) :: & timeinc_old, & @@ -289,45 +297,18 @@ subroutine grid_mech_FEM_forward(guess,timeinc,timeinc_old,loadCaseTime,deformat type(tBoundaryCondition), intent(in) :: & stress_BC, & deformation_BC - real(pReal), dimension(3,3), intent(in) :: & + type(rotation), intent(in) :: & rotation_BC PetscErrorCode :: ierr - integer(HID_T) :: fileHandle - character(len=32) :: rankStr - PetscScalar, pointer, dimension(:,:,:,:) :: & - u_current,u_lastInc + PetscScalar, pointer, dimension(:,:,:,:) :: & + 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) if (cutBack) then - C_volAvg = C_volAvgLastInc ! QUESTION: where is this required? + C_volAvg = C_volAvgLastInc else - !-------------------------------------------------------------------------------------------------- - ! restart information for spectral solver - if (restartWrite) then - write(6,'(/,a)') ' writing converged results for restart';flush(6) - - write(rankStr,'(a1,i0)')'_',worldrank - fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5','w') - - call HDF5_write(fileHandle,F_aim, 'F_aim') - call HDF5_write(fileHandle,F_aim_lastInc, 'F_aim_lastInc') - call HDF5_write(fileHandle,F_aimDot, 'F_aimDot') - call HDF5_write(fileHandle,F, 'F') - call HDF5_write(fileHandle,F_lastInc, 'F_lastInc') - call HDF5_write(fileHandle,u_current, 'u') - call HDF5_write(fileHandle,u_lastInc, 'u_lastInc') - - call HDF5_write(fileHandle,C_volAvg, 'C_volAvg') - call HDF5_write(fileHandle,C_volAvgLastInc,'C_volAvgLastInc') - - call HDF5_closeFile(fileHandle) - - endif - call CPFEM_age ! age state and kinematics - call utilities_updateIPcoords(F) - C_volAvgLastInc = C_volAvg F_aimDot = merge(stress_BC%maskFloat*(F_aim-F_aim_lastInc)/timeinc_old, 0.0_pReal, guess) @@ -345,7 +326,6 @@ subroutine grid_mech_FEM_forward(guess,timeinc,timeinc_old,loadCaseTime,deformat F_aimDot = & F_aimDot + deformation_BC%maskFloat * (deformation_BC%values - F_aim_lastInc)/loadCaseTime endif - if (guess) then call VecWAXPY(solution_rate,-1.0_pReal,solution_lastInc,solution_current,ierr) @@ -356,9 +336,9 @@ subroutine grid_mech_FEM_forward(guess,timeinc,timeinc_old,loadCaseTime,deformat endif call VecCopy(solution_current,solution_lastInc,ierr); CHKERRQ(ierr) - F_lastInc = F ! winding F forward - materialpoint_F0 = reshape(F_lastInc, [3,3,1,product(grid(1:2))*grid3]) ! set starting condition for materialpoint_stressAndItsTangent - + F_lastInc = F + + materialpoint_F0 = reshape(F, [3,3,1,product(grid(1:2))*grid3]) endif !-------------------------------------------------------------------------------------------------- @@ -366,14 +346,61 @@ subroutine grid_mech_FEM_forward(guess,timeinc,timeinc_old,loadCaseTime,deformat F_aim = F_aim_lastInc + F_aimDot * timeinc call VecAXPY(solution_current,timeinc,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(mech_grid,solution_current,u_current,ierr);CHKERRQ(ierr) + call DMDAVecRestoreArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr);CHKERRQ(ierr) end subroutine grid_mech_FEM_forward +!-------------------------------------------------------------------------------------------------- +!> @brief Age +!-------------------------------------------------------------------------------------------------- +subroutine grid_mech_FEM_updateCoords() + + call utilities_updateCoords(F) + +end subroutine grid_mech_FEM_updateCoords + + +!-------------------------------------------------------------------------------------------------- +!> @brief Write current solver and constitutive data for restart to file +!-------------------------------------------------------------------------------------------------- +subroutine grid_mech_FEM_restartWrite() + + PetscErrorCode :: ierr + PetscScalar, dimension(:,:,:,:), pointer :: u_current,u_lastInc + integer(HID_T) :: fileHandle, groupHandle + character(len=32) :: rankStr + + call DMDAVecGetArrayF90(mech_grid,solution_current,u_current,ierr); CHKERRQ(ierr) + call DMDAVecGetArrayF90(mech_grid,solution_lastInc,u_lastInc,ierr); CHKERRQ(ierr) + + write(6,'(a)') ' writing solver data required for restart to file';flush(6) + + write(rankStr,'(a1,i0)')'_',worldrank + fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5','w') + groupHandle = HDF5_addGroup(fileHandle,'solver') + + call HDF5_write(groupHandle,F_aim, 'F_aim') + call HDF5_write(groupHandle,F_aim_lastInc,'F_aim_lastInc') + call HDF5_write(groupHandle,F_aimDot, 'F_aimDot') + call HDF5_write(groupHandle,F, 'F') + call HDF5_write(groupHandle,F_lastInc, 'F_lastInc') + call HDF5_write(groupHandle,u_current, 'u') + call HDF5_write(groupHandle,u_lastInc, 'u_lastInc') + + call HDF5_write(groupHandle,C_volAvg, 'C_volAvg') + call HDF5_write(groupHandle,C_volAvgLastInc,'C_volAvgLastInc') + + 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) + +end subroutine grid_mech_FEM_restartWrite + + !-------------------------------------------------------------------------------------------------- !> @brief convergence check !-------------------------------------------------------------------------------------------------- @@ -455,7 +482,7 @@ subroutine formResidual(da_local,x_local, & trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter+1, '≤', itmax if (iand(debug_level(debug_spectral),debug_spectralRotation) /= 0) & write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & - ' deformation gradient aim (lab) =', transpose(math_rotate_backward33(F_aim,params%rotation_BC)) + ' deformation gradient aim (lab) =', transpose(params%rotation_BC%rotTensor2(F_aim,active=.true.)) write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & ' deformation gradient aim =', transpose(F_aim) flush(6) @@ -471,7 +498,7 @@ subroutine formResidual(da_local,x_local, & x_elem(ctr,1:3) = x_scal(0:2,i+ii,j+jj,k+kk) enddo; enddo; enddo ii = i-xstart+1; jj = j-ystart+1; kk = k-zstart+1 - F(1:3,1:3,ii,jj,kk) = math_rotate_backward33(F_aim,params%rotation_BC) + transpose(matmul(BMat,x_elem)) + F(1:3,1:3,ii,jj,kk) = params%rotation_BC%rotTensor2(F_aim,active=.true.) + transpose(matmul(BMat,x_elem)) enddo; enddo; enddo call DMDAVecRestoreArrayF90(da_local,x_local,x_scal,ierr);CHKERRQ(ierr) @@ -549,7 +576,7 @@ subroutine formJacobian(da_local,x_local,Jac_pre,Jac,dummy,ierr) PetscScalar,dimension(24,24) :: K_ele PetscScalar,dimension(9,24) :: BMatFull PetscInt :: i, ii, j, jj, k, kk, ctr, ele - PetscInt,dimension(3) :: rows + PetscInt,dimension(3),parameter :: rows = [0, 1, 2] PetscScalar :: diag PetscObject :: dummy MatNullSpace :: matnull @@ -606,7 +633,6 @@ subroutine formJacobian(da_local,x_local,Jac_pre,Jac,dummy,ierr) !-------------------------------------------------------------------------------------------------- ! applying boundary conditions - rows = [0, 1, 2] diag = (C_volAvg(1,1,1,1)/delta(1)**2.0_pReal + & C_volAvg(2,2,2,2)/delta(2)**2.0_pReal + & C_volAvg(3,3,3,3)/delta(3)**2.0_pReal)*detJ diff --git a/src/grid/grid_mech_spectral_basic.f90 b/src/grid/grid_mech_spectral_basic.f90 index b7b43eeef..36caabf90 100644 --- a/src/grid/grid_mech_spectral_basic.f90 +++ b/src/grid/grid_mech_spectral_basic.f90 @@ -20,7 +20,7 @@ module grid_mech_spectral_basic use config use numerics use homogenization - use mesh + use mesh_grid use CPFEM2 use debug @@ -75,10 +75,9 @@ module grid_mech_spectral_basic public :: & grid_mech_spectral_basic_init, & grid_mech_spectral_basic_solution, & - grid_mech_spectral_basic_forward - private :: & - converged, & - formResidual + grid_mech_spectral_basic_forward, & + grid_mech_spectral_basic_updateCoords, & + grid_mech_spectral_basic_restartWrite contains @@ -95,8 +94,8 @@ subroutine grid_mech_spectral_basic_init PetscScalar, pointer, dimension(:,:,:,:) :: & F ! pointer to solution data PetscInt, dimension(worldsize) :: localK - integer(HID_T) :: fileHandle - integer :: fileUnit + integer(HID_T) :: fileHandle, groupHandle + integer :: fileUnit character(len=1024) :: rankStr write(6,'(/,a)') ' <<<+- grid_mech_spectral_basic init -+>>>' @@ -151,18 +150,19 @@ subroutine grid_mech_spectral_basic_init ! init fields call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) ! places pointer on PETSc data - restartRead: if (interface_restartInc > 0) then + restartRead: if (interface_restartInc > 0) then write(6,'(/,a,'//IO_intOut(interface_restartInc)//',a)') & ' reading values of increment ', interface_restartInc, ' from file' write(rankStr,'(a1,i0)')'_',worldrank - fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5') + fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5') + groupHandle = HDF5_openGroup(fileHandle,'solver') - call HDF5_read(fileHandle,F_aim, 'F_aim') - call HDF5_read(fileHandle,F_aim_lastInc,'F_aim_lastInc') - call HDF5_read(fileHandle,F_aimDot, 'F_aimDot') - call HDF5_read(fileHandle,F, 'F') - call HDF5_read(fileHandle,F_lastInc, 'F_lastInc') + call HDF5_read(groupHandle,F_aim, 'F_aim') + call HDF5_read(groupHandle,F_aim_lastInc,'F_aim_lastInc') + call HDF5_read(groupHandle,F_aimDot, 'F_aimDot') + call HDF5_read(groupHandle,F, 'F') + call HDF5_read(groupHandle,F_lastInc, 'F_lastInc') elseif (interface_restartInc == 0) then restartRead F_lastInc = spread(spread(spread(math_I3,3,grid(1)),4,grid(2)),5,grid3) ! initialize to identity @@ -170,18 +170,19 @@ subroutine grid_mech_spectral_basic_init endif restartRead materialpoint_F0 = reshape(F_lastInc, [3,3,1,product(grid(1:2))*grid3]) ! set starting condition for materialpoint_stressAndItsTangent - call Utilities_updateIPcoords(reshape(F,shape(F_lastInc))) + call Utilities_updateCoords(reshape(F,shape(F_lastInc))) call Utilities_constitutiveResponse(P,temp33_Real,C_volAvg,C_minMaxAvg, & ! stress field, stress avg, global average of stiffness and (min+max)/2 reshape(F,shape(F_lastInc)), & ! target F - 0.0_pReal, & ! time increment - math_I3) ! no rotation of boundary condition + 0.0_pReal) ! time increment call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) ! deassociate pointer restartRead2: if (interface_restartInc > 0) then write(6,'(/,a,'//IO_intOut(interface_restartInc)//',a)') & 'reading more values of increment ', interface_restartInc, ' from file' - call HDF5_read(fileHandle,C_volAvg, 'C_volAvg') - call HDF5_read(fileHandle,C_volAvgLastInc,'C_volAvgLastInc') + call HDF5_read(groupHandle,C_volAvg, 'C_volAvg') + call HDF5_read(groupHandle,C_volAvgLastInc,'C_volAvgLastInc') + + call HDF5_closeGroup(groupHandle) call HDF5_closeFile(fileHandle) call MPI_File_open(PETSC_COMM_WORLD, trim(getSolverJobName())//'.C_ref', & @@ -190,7 +191,8 @@ subroutine grid_mech_spectral_basic_init call MPI_File_close(fileUnit,ierr) endif restartRead2 - call utilities_updateGamma(C_minMaxAvg,.true.) + call utilities_updateGamma(C_minMaxAvg) + call utilities_saveReferenceStiffness end subroutine grid_mech_spectral_basic_init @@ -209,7 +211,8 @@ function grid_mech_spectral_basic_solution(incInfoIn,timeinc,timeinc_old,stress_ timeinc_old !< time increment of last successful increment type(tBoundaryCondition), intent(in) :: & stress_BC - real(pReal), dimension(3,3), intent(in) :: rotation_BC + type(rotation), intent(in) :: & + rotation_BC type(tSolutionState) :: & solution !-------------------------------------------------------------------------------------------------- @@ -222,8 +225,8 @@ function grid_mech_spectral_basic_solution(incInfoIn,timeinc,timeinc_old,stress_ !-------------------------------------------------------------------------------------------------- ! update stiffness (and gamma operator) S = utilities_maskedCompliance(rotation_BC,stress_BC%maskLogical,C_volAvg) - if (num%update_gamma) call utilities_updateGamma(C_minMaxAvg,restartWrite) - + if(num%update_gamma) call utilities_updateGamma(C_minMaxAvg) + !-------------------------------------------------------------------------------------------------- ! set module wide available data params%stress_mask = stress_BC%maskFloat @@ -253,9 +256,11 @@ end function grid_mech_spectral_basic_solution !> @details find new boundary conditions and best F estimate for end of current timestep !> possibly writing restart information, triggering of state increment in DAMASK, and updating of IPcoordinates !-------------------------------------------------------------------------------------------------- -subroutine grid_mech_spectral_basic_forward(guess,timeinc,timeinc_old,loadCaseTime,deformation_BC,stress_BC,rotation_BC) +subroutine grid_mech_spectral_basic_forward(cutBack,guess,timeinc,timeinc_old,loadCaseTime,& + deformation_BC,stress_BC,rotation_BC) logical, intent(in) :: & + cutBack, & guess real(pReal), intent(in) :: & timeinc_old, & @@ -264,44 +269,17 @@ subroutine grid_mech_spectral_basic_forward(guess,timeinc,timeinc_old,loadCaseTi type(tBoundaryCondition), intent(in) :: & stress_BC, & deformation_BC - real(pReal), dimension(3,3), intent(in) :: & + type(rotation), intent(in) :: & rotation_BC PetscErrorCode :: ierr PetscScalar, dimension(:,:,:,:), pointer :: F - - integer(HID_T) :: fileHandle - character(len=32) :: rankStr call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) if (cutBack) then - C_volAvg = C_volAvgLastInc ! QUESTION: where is this required? - C_minMaxAvg = C_minMaxAvgLastInc ! QUESTION: where is this required? + C_volAvg = C_volAvgLastInc + C_minMaxAvg = C_minMaxAvgLastInc else - !-------------------------------------------------------------------------------------------------- - ! restart information for spectral solver - if (restartWrite) then - write(6,'(/,a)') ' writing converged results for restart';flush(6) - - write(rankStr,'(a1,i0)')'_',worldrank - fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5','w') - - call HDF5_write(fileHandle,F_aim, 'F_aim') - call HDF5_write(fileHandle,F_aim_lastInc,'F_aim_lastInc') - call HDF5_write(fileHandle,F_aimDot, 'F_aimDot') - call HDF5_write(fileHandle,F, 'F') - call HDF5_write(fileHandle,F_lastInc, 'F_lastInc') - - call HDF5_write(fileHandle,C_volAvg, 'C_volAvg') - call HDF5_write(fileHandle,C_volAvgLastInc,'C_volAvgLastInc') - call HDF5_write(fileHandle,C_minMaxAvg, 'C_minMaxAvg') - - call HDF5_closeFile(fileHandle) - endif - - call CPFEM_age ! age state and kinematics - call utilities_updateIPcoords(F) - C_volAvgLastInc = C_volAvg C_minMaxAvgLastInc = C_minMaxAvg @@ -310,35 +288,88 @@ subroutine grid_mech_spectral_basic_forward(guess,timeinc,timeinc_old,loadCaseTi !-------------------------------------------------------------------------------------------------- ! calculate rate for aim - if (deformation_BC%myType=='l') then ! calculate F_aimDot from given L and current F + if (deformation_BC%myType=='l') then ! calculate F_aimDot from given L and current F F_aimDot = & F_aimDot + deformation_BC%maskFloat * matmul(deformation_BC%values, F_aim_lastInc) - elseif(deformation_BC%myType=='fdot') then ! F_aimDot is prescribed + elseif(deformation_BC%myType=='fdot') then ! F_aimDot is prescribed F_aimDot = & F_aimDot + deformation_BC%maskFloat * deformation_BC%values - elseif (deformation_BC%myType=='f') then ! aim at end of load case is prescribed + elseif (deformation_BC%myType=='f') then ! aim at end of load case is prescribed F_aimDot = & F_aimDot + deformation_BC%maskFloat * (deformation_BC%values - F_aim_lastInc)/loadCaseTime endif - - Fdot = utilities_calculateRate(guess, & - F_lastInc,reshape(F,[3,3,grid(1),grid(2),grid3]),timeinc_old, & - math_rotate_backward33(F_aimDot,rotation_BC)) - F_lastInc = reshape(F, [3,3,grid(1),grid(2),grid3]) ! winding F forward - materialpoint_F0 = reshape(F_lastInc, [3,3,1,product(grid(1:2))*grid3]) ! set starting condition for materialpoint_stressAndItsTangent + Fdot = utilities_calculateRate(guess, & + F_lastInc,reshape(F,[3,3,grid(1),grid(2),grid3]),timeinc_old, & + rotation_BC%rotTensor2(F_aimDot,active=.true.)) + F_lastInc = reshape(F,[3,3,grid(1),grid(2),grid3]) + + materialpoint_F0 = reshape(F, [3,3,1,product(grid(1:2))*grid3]) endif !-------------------------------------------------------------------------------------------------- ! update average and local deformation gradients F_aim = F_aim_lastInc + F_aimDot * timeinc F = reshape(Utilities_forwardField(timeinc,F_lastInc,Fdot, & ! estimate of F at end of time+timeinc that matches rotated F_aim on average - math_rotate_backward33(F_aim,rotation_BC)),[9,grid(1),grid(2),grid3]) + rotation_BC%rotTensor2(F_aim,active=.true.)),[9,grid(1),grid(2),grid3]) call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) end subroutine grid_mech_spectral_basic_forward +!-------------------------------------------------------------------------------------------------- +!> @brief Age +!-------------------------------------------------------------------------------------------------- +subroutine grid_mech_spectral_basic_updateCoords() + + PetscErrorCode :: ierr + PetscScalar, dimension(:,:,:,:), pointer :: F + + call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) + call utilities_updateCoords(F) + call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) + +end subroutine grid_mech_spectral_basic_updateCoords + + +!-------------------------------------------------------------------------------------------------- +!> @brief Write current solver and constitutive data for restart to file +!-------------------------------------------------------------------------------------------------- +subroutine grid_mech_spectral_basic_restartWrite() + + PetscErrorCode :: ierr + PetscScalar, dimension(:,:,:,:), pointer :: F + integer(HID_T) :: fileHandle, groupHandle + character(len=32) :: rankStr + + call DMDAVecGetArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) + + write(6,'(a)') ' writing solver data required for restart to file';flush(6) + + write(rankStr,'(a1,i0)')'_',worldrank + fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5','w') + groupHandle = HDF5_addGroup(fileHandle,'solver') + + call HDF5_write(groupHandle,F_aim, 'F_aim') + call HDF5_write(groupHandle,F_aim_lastInc,'F_aim_lastInc') + call HDF5_write(groupHandle,F_aimDot, 'F_aimDot') + call HDF5_write(groupHandle,F, 'F') + call HDF5_write(groupHandle,F_lastInc, 'F_lastInc') + + call HDF5_write(groupHandle,C_volAvg, 'C_volAvg') + call HDF5_write(groupHandle,C_volAvgLastInc,'C_volAvgLastInc') + call HDF5_write(groupHandle,C_minMaxAvg, 'C_minMaxAvg') + + call HDF5_closeGroup(groupHandle) + call HDF5_closeFile(fileHandle) + + if (num%update_gamma) call utilities_saveReferenceStiffness + + call DMDAVecRestoreArrayF90(da,solution_vec,F,ierr); CHKERRQ(ierr) + +end subroutine grid_mech_spectral_basic_restartWrite + + !-------------------------------------------------------------------------------------------------- !> @brief convergence check !-------------------------------------------------------------------------------------------------- @@ -415,7 +446,7 @@ subroutine formResidual(in, F, & trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter, '≤', itmax if (iand(debug_level(debug_spectral),debug_spectralRotation) /= 0) & write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & - ' deformation gradient aim (lab) =', transpose(math_rotate_backward33(F_aim,params%rotation_BC)) + ' deformation gradient aim (lab) =', transpose(params%rotation_BC%rotTensor2(F_aim,active=.true.)) write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & ' deformation gradient aim =', transpose(F_aim) flush(6) @@ -440,7 +471,7 @@ subroutine formResidual(in, F, & tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3) = residuum ! store fPK field for subsequent FFT forward transform call utilities_FFTtensorForward ! FFT forward of global "tensorField_real" err_div = Utilities_divergenceRMS() ! divRMS of tensorField_fourier for later use - call utilities_fourierGammaConvolution(math_rotate_backward33(deltaF_aim,params%rotation_BC)) ! convolution of Gamma and tensorField_fourier, with arg + call utilities_fourierGammaConvolution(params%rotation_BC%rotTensor2(deltaF_aim,active=.true.)) ! convolution of Gamma and tensorField_fourier call utilities_FFTtensorBackward ! FFT backward of global tensorField_fourier !-------------------------------------------------------------------------------------------------- diff --git a/src/grid/grid_mech_spectral_polarisation.f90 b/src/grid/grid_mech_spectral_polarisation.f90 index 3f730cc3b..07d9a5afc 100644 --- a/src/grid/grid_mech_spectral_polarisation.f90 +++ b/src/grid/grid_mech_spectral_polarisation.f90 @@ -14,13 +14,14 @@ module grid_mech_spectral_polarisation use DAMASK_interface use HDF5_utilities use math + use rotations use spectral_utilities use IO use FEsolving use config use numerics use homogenization - use mesh + use mesh_grid use CPFEM2 use debug @@ -81,10 +82,9 @@ module grid_mech_spectral_polarisation public :: & grid_mech_spectral_polarisation_init, & grid_mech_spectral_polarisation_solution, & - grid_mech_spectral_polarisation_forward - private :: & - converged, & - formResidual + grid_mech_spectral_polarisation_forward, & + grid_mech_spectral_polarisation_updateCoords, & + grid_mech_spectral_polarisation_restartWrite contains @@ -103,8 +103,8 @@ subroutine grid_mech_spectral_polarisation_init F, & ! specific (sub)pointer F_tau ! specific (sub)pointer PetscInt, dimension(worldsize) :: localK - integer(HID_T) :: fileHandle - integer :: fileUnit + integer(HID_T) :: fileHandle, groupHandle + integer :: fileUnit character(len=1024) :: rankStr write(6,'(/,a)') ' <<<+- grid_mech_spectral_polarisation init -+>>>' @@ -157,23 +157,24 @@ subroutine grid_mech_spectral_polarisation_init !-------------------------------------------------------------------------------------------------- ! init fields call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) ! places pointer on PETSc data - F => FandF_tau( 0: 8,:,:,:) - F_tau => FandF_tau( 9:17,:,:,:) + F => FandF_tau(0: 8,:,:,:) + F_tau => FandF_tau(9:17,:,:,:) restartRead: if (interface_restartInc > 0) then write(6,'(/,a,'//IO_intOut(interface_restartInc)//',a)') & ' reading values of increment ', interface_restartInc, ' from file' write(rankStr,'(a1,i0)')'_',worldrank - fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5') + fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5') + groupHandle = HDF5_openGroup(fileHandle,'solver') - call HDF5_read(fileHandle,F_aim, 'F_aim') - call HDF5_read(fileHandle,F_aim_lastInc,'F_aim_lastInc') - call HDF5_read(fileHandle,F_aimDot, 'F_aimDot') - call HDF5_read(fileHandle,F, 'F') - call HDF5_read(fileHandle,F_lastInc, 'F_lastInc') - call HDF5_read(fileHandle,F_tau, 'F_tau') - call HDF5_read(fileHandle,F_tau_lastInc,'F_tau_lastInc') + call HDF5_read(groupHandle,F_aim, 'F_aim') + call HDF5_read(groupHandle,F_aim_lastInc,'F_aim_lastInc') + call HDF5_read(groupHandle,F_aimDot, 'F_aimDot') + call HDF5_read(groupHandle,F, 'F') + call HDF5_read(groupHandle,F_lastInc, 'F_lastInc') + call HDF5_read(groupHandle,F_tau, 'F_tau') + call HDF5_read(groupHandle,F_tau_lastInc,'F_tau_lastInc') elseif (interface_restartInc == 0) then restartRead F_lastInc = spread(spread(spread(math_I3,3,grid(1)),4,grid(2)),5,grid3) ! initialize to identity @@ -183,18 +184,19 @@ subroutine grid_mech_spectral_polarisation_init endif restartRead materialpoint_F0 = reshape(F_lastInc, [3,3,1,product(grid(1:2))*grid3]) ! set starting condition for materialpoint_stressAndItsTangent - call Utilities_updateIPcoords(reshape(F,shape(F_lastInc))) + call Utilities_updateCoords(reshape(F,shape(F_lastInc))) call Utilities_constitutiveResponse(P,temp33_Real,C_volAvg,C_minMaxAvg, & ! stress field, stress avg, global average of stiffness and (min+max)/2 reshape(F,shape(F_lastInc)), & ! target F - 0.0_pReal, & ! time increment - math_I3) ! no rotation of boundary condition + 0.0_pReal) ! time increment call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) ! deassociate pointer restartRead2: if (interface_restartInc > 0) then write(6,'(/,a,'//IO_intOut(interface_restartInc)//',a)') & ' reading more values of increment ', interface_restartInc, ' from file' - call HDF5_read(fileHandle,C_volAvg, 'C_volAvg') - call HDF5_read(fileHandle,C_volAvgLastInc,'C_volAvgLastInc') + call HDF5_read(groupHandle,C_volAvg, 'C_volAvg') + call HDF5_read(groupHandle,C_volAvgLastInc,'C_volAvgLastInc') + + call HDF5_closeGroup(groupHandle) call HDF5_closeFile(fileHandle) call MPI_File_open(PETSC_COMM_WORLD, trim(getSolverJobName())//'.C_ref', & @@ -203,7 +205,8 @@ subroutine grid_mech_spectral_polarisation_init call MPI_File_close(fileUnit,ierr) endif restartRead2 - call utilities_updateGamma(C_minMaxAvg,.true.) + call utilities_updateGamma(C_minMaxAvg) + call utilities_saveReferenceStiffness C_scale = C_minMaxAvg S_scale = math_invSym3333(C_minMaxAvg) @@ -219,12 +222,13 @@ function grid_mech_spectral_polarisation_solution(incInfoIn,timeinc,timeinc_old, ! input data for solution character(len=*), intent(in) :: & incInfoIn - real(pReal), intent(in) :: & + real(pReal), intent(in) :: & timeinc, & !< time increment of current solution timeinc_old !< time increment of last successful increment type(tBoundaryCondition), intent(in) :: & stress_BC - real(pReal), dimension(3,3), intent(in) :: rotation_BC + type(rotation), intent(in) :: & + rotation_BC type(tSolutionState) :: & solution !-------------------------------------------------------------------------------------------------- @@ -238,7 +242,7 @@ function grid_mech_spectral_polarisation_solution(incInfoIn,timeinc,timeinc_old, ! update stiffness (and gamma operator) S = utilities_maskedCompliance(rotation_BC,stress_BC%maskLogical,C_volAvg) if (num%update_gamma) then - call utilities_updateGamma(C_minMaxAvg,restartWrite) + call utilities_updateGamma(C_minMaxAvg) C_scale = C_minMaxAvg S_scale = math_invSym3333(C_minMaxAvg) endif @@ -272,9 +276,11 @@ end function grid_mech_spectral_polarisation_solution !> @details find new boundary conditions and best F estimate for end of current timestep !> possibly writing restart information, triggering of state increment in DAMASK, and updating of IPcoordinates !-------------------------------------------------------------------------------------------------- -subroutine grid_mech_spectral_polarisation_forward(guess,timeinc,timeinc_old,loadCaseTime,deformation_BC,stress_BC,rotation_BC) +subroutine grid_mech_spectral_polarisation_forward(cutBack,guess,timeinc,timeinc_old,loadCaseTime,& + deformation_BC,stress_BC,rotation_BC) - logical, intent(in) :: & + logical, intent(in) :: & + cutBack, & guess real(pReal), intent(in) :: & timeinc_old, & @@ -283,56 +289,28 @@ subroutine grid_mech_spectral_polarisation_forward(guess,timeinc,timeinc_old,loa type(tBoundaryCondition), intent(in) :: & stress_BC, & deformation_BC - real(pReal), dimension(3,3), intent(in) ::& + type(rotation), intent(in) :: & rotation_BC PetscErrorCode :: ierr PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau, F, F_tau integer :: i, j, k real(pReal), dimension(3,3) :: F_lambda33 - integer(HID_T) :: fileHandle - character(len=32) :: rankStr - call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) - F => FandF_tau( 0: 8,:,:,:) - F_tau => FandF_tau( 9:17,:,:,:) + F => FandF_tau(0: 8,:,:,:) + F_tau => FandF_tau(9:17,:,:,:) if (cutBack) then - C_volAvg = C_volAvgLastInc ! QUESTION: where is this required? - C_minMaxAvg = C_minMaxAvgLastInc ! QUESTION: where is this required? - else - !-------------------------------------------------------------------------------------------------- - ! restart information for spectral solver - if (restartWrite) then - write(6,'(/,a)') ' writing converged results for restart';flush(6) - - write(rankStr,'(a1,i0)')'_',worldrank - fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5','w') - - call HDF5_write(fileHandle,F_aim, 'F_aim') - call HDF5_write(fileHandle,F_aim_lastInc, 'F_aim_lastInc') - call HDF5_write(fileHandle,F_aimDot, 'F_aimDot') - call HDF5_write(fileHandle,F, 'F') - call HDF5_write(fileHandle,F_lastInc, 'F_lastInc') - call HDF5_write(fileHandle,F_tau, 'F_tau') - call HDF5_write(fileHandle,F_tau_lastInc, 'F_tau_lastInc') - - call HDF5_write(fileHandle,C_volAvg, 'C_volAvg') - call HDF5_write(fileHandle,C_volAvgLastInc,'C_volAvgLastInc') - - call HDF5_closeFile(fileHandle) - endif - - call CPFEM_age ! age state and kinematics - call utilities_updateIPcoords(F) - + C_volAvg = C_volAvgLastInc + C_minMaxAvg = C_minMaxAvgLastInc + else C_volAvgLastInc = C_volAvg C_minMaxAvgLastInc = C_minMaxAvg F_aimDot = merge(stress_BC%maskFloat*(F_aim-F_aim_lastInc)/timeinc_old, 0.0_pReal, guess) F_aim_lastInc = F_aim - !-------------------------------------------------------------------------------------------------- + !----------------------------------------------------------------------------------------------- ! calculate rate for aim if (deformation_BC%myType=='l') then ! calculate F_aimDot from given L and current F F_aimDot = & @@ -345,23 +323,23 @@ subroutine grid_mech_spectral_polarisation_forward(guess,timeinc,timeinc_old,loa F_aimDot + deformation_BC%maskFloat * (deformation_BC%values - F_aim_lastInc)/loadCaseTime endif - - Fdot = utilities_calculateRate(guess, & - F_lastInc,reshape(F,[3,3,grid(1),grid(2),grid3]),timeinc_old, & - math_rotate_backward33(F_aimDot,rotation_BC)) - F_tauDot = utilities_calculateRate(guess, & - F_tau_lastInc,reshape(F_tau,[3,3,grid(1),grid(2),grid3]), timeinc_old, & - math_rotate_backward33(F_aimDot,rotation_BC)) - F_lastInc = reshape(F, [3,3,grid(1),grid(2),grid3]) ! winding F forward - F_tau_lastInc = reshape(F_tau, [3,3,grid(1),grid(2),grid3]) ! winding F_tau forward - materialpoint_F0 = reshape(F_lastInc, [3,3,1,product(grid(1:2))*grid3]) ! set starting condition for materialpoint_stressAndItsTangent + Fdot = utilities_calculateRate(guess, & + F_lastInc,reshape(F,[3,3,grid(1),grid(2),grid3]),timeinc_old, & + rotation_BC%rotTensor2(F_aimDot,active=.true.)) + F_tauDot = utilities_calculateRate(guess, & + F_tau_lastInc,reshape(F_tau,[3,3,grid(1),grid(2),grid3]), timeinc_old, & + rotation_BC%rotTensor2(F_aimDot,active=.true.)) + F_lastInc = reshape(F, [3,3,grid(1),grid(2),grid3]) + F_tau_lastInc = reshape(F_tau,[3,3,grid(1),grid(2),grid3]) + + materialpoint_F0 = reshape(F,[3,3,1,product(grid(1:2))*grid3]) endif !-------------------------------------------------------------------------------------------------- ! update average and local deformation gradients F_aim = F_aim_lastInc + F_aimDot * timeinc F = reshape(utilities_forwardField(timeinc,F_lastInc,Fdot, & ! estimate of F at end of time+timeinc that matches rotated F_aim on average - math_rotate_backward33(F_aim,rotation_BC)),& + rotation_BC%rotTensor2(F_aim,active=.true.)),& [9,grid(1),grid(2),grid3]) if (guess) then F_tau = reshape(Utilities_forwardField(timeinc,F_tau_lastInc,F_taudot), & @@ -372,8 +350,8 @@ subroutine grid_mech_spectral_polarisation_forward(guess,timeinc,timeinc_old,loa F_lambda33 = math_mul3333xx33(S_scale,matmul(F_lambda33, & math_mul3333xx33(C_scale,& matmul(transpose(F_lambda33),& - F_lambda33)-math_I3))*0.5_pReal)& - + math_I3 + F_lambda33)-math_I3))*0.5_pReal) & + + math_I3 F_tau(1:9,i,j,k) = reshape(F_lambda33,[9])+F(1:9,i,j,k) enddo; enddo; enddo endif @@ -383,6 +361,62 @@ subroutine grid_mech_spectral_polarisation_forward(guess,timeinc,timeinc_old,loa end subroutine grid_mech_spectral_polarisation_forward +!-------------------------------------------------------------------------------------------------- +!> @brief Age +!-------------------------------------------------------------------------------------------------- +subroutine grid_mech_spectral_polarisation_updateCoords() + + PetscErrorCode :: ierr + PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau + + call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) + call utilities_updateCoords(FandF_tau(0:8,:,:,:)) + call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) + +end subroutine grid_mech_spectral_polarisation_updateCoords + + +!-------------------------------------------------------------------------------------------------- +!> @brief Write current solver and constitutive data for restart to file +!-------------------------------------------------------------------------------------------------- +subroutine grid_mech_spectral_polarisation_restartWrite() + + PetscErrorCode :: ierr + PetscScalar, dimension(:,:,:,:), pointer :: FandF_tau, F, F_tau + integer(HID_T) :: fileHandle, groupHandle + character(len=32) :: rankStr + + call DMDAVecGetArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) + F => FandF_tau(0: 8,:,:,:) + F_tau => FandF_tau(9:17,:,:,:) + + write(6,'(a)') ' writing solver data required for restart to file';flush(6) + + write(rankStr,'(a1,i0)')'_',worldrank + fileHandle = HDF5_openFile(trim(getSolverJobName())//trim(rankStr)//'.hdf5','w') + groupHandle = HDF5_addGroup(fileHandle,'solver') + + call HDF5_write(groupHandle,F_aim, 'F_aim') + call HDF5_write(groupHandle,F_aim_lastInc,'F_aim_lastInc') + call HDF5_write(groupHandle,F_aimDot, 'F_aimDot') + call HDF5_write(groupHandle,F, 'F') + call HDF5_write(groupHandle,F_lastInc, 'F_lastInc') + call HDF5_write(groupHandle,F_tau, 'F_tau') + call HDF5_write(groupHandle,F_tau_lastInc,'F_tau_lastInc') + + call HDF5_write(groupHandle,C_volAvg, 'C_volAvg') + call HDF5_write(groupHandle,C_volAvgLastInc,'C_volAvgLastInc') + + call HDF5_closeGroup(groupHandle) + call HDF5_closeFile(fileHandle) + + if(num%update_gamma) call utilities_saveReferenceStiffness + + call DMDAVecRestoreArrayF90(da,solution_vec,FandF_tau,ierr); CHKERRQ(ierr) + +end subroutine grid_mech_spectral_polarisation_restartWrite + + !-------------------------------------------------------------------------------------------------- !> @brief convergence check !-------------------------------------------------------------------------------------------------- @@ -457,13 +491,13 @@ subroutine formResidual(in, FandF_tau, & integer :: & i, j, k, e - F => FandF_tau(1:3,1:3,1,& + F => FandF_tau(1:3,1:3,1,& XG_RANGE,YG_RANGE,ZG_RANGE) - F_tau => FandF_tau(1:3,1:3,2,& + F_tau => FandF_tau(1:3,1:3,2,& XG_RANGE,YG_RANGE,ZG_RANGE) - residual_F => residuum(1:3,1:3,1,& + residual_F => residuum(1:3,1:3,1,& X_RANGE, Y_RANGE, Z_RANGE) - residual_F_tau => residuum(1:3,1:3,2,& + residual_F_tau => residuum(1:3,1:3,2,& X_RANGE, Y_RANGE, Z_RANGE) F_av = sum(sum(sum(F,dim=5),dim=4),dim=3) * wgt @@ -481,7 +515,7 @@ subroutine formResidual(in, FandF_tau, & trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter, '≤', itmax if (iand(debug_level(debug_spectral),debug_spectralRotation) /= 0) & write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & - ' deformation gradient aim (lab) =', transpose(math_rotate_backward33(F_aim,params%rotation_BC)) + ' deformation gradient aim (lab) =', transpose(params%rotation_BC%rotTensor2(F_aim,active=.true.)) write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & ' deformation gradient aim =', transpose(F_aim) flush(6) @@ -500,7 +534,7 @@ subroutine formResidual(in, FandF_tau, & !-------------------------------------------------------------------------------------------------- ! doing convolution in Fourier space call utilities_FFTtensorForward - call utilities_fourierGammaConvolution(math_rotate_backward33(polarBeta*F_aim,params%rotation_BC)) + call utilities_fourierGammaConvolution(params%rotation_BC%rotTensor2(polarBeta*F_aim,active=.true.)) call utilities_FFTtensorBackward !-------------------------------------------------------------------------------------------------- @@ -518,7 +552,7 @@ subroutine formResidual(in, FandF_tau, & ! stress BC handling F_aim = F_aim - math_mul3333xx33(S, ((P_av - params%stress_BC))) ! S = 0.0 for no bc err_BC = maxval(abs((1.0_pReal-params%stress_mask) * math_mul3333xx33(C_scale,F_aim & - -math_rotate_forward33(F_av,params%rotation_BC)) + & + -params%rotation_BC%rotTensor2(F_av)) + & params%stress_mask * (P_av-params%stress_BC))) ! mask = 0.0 for no bc ! calculate divergence tensorField_real = 0.0_pReal diff --git a/src/grid/grid_thermal_spectral.f90 b/src/grid/grid_thermal_spectral.f90 index 2977faf2b..c7f886f13 100644 --- a/src/grid/grid_thermal_spectral.f90 +++ b/src/grid/grid_thermal_spectral.f90 @@ -12,7 +12,7 @@ module grid_thermal_spectral use prec use spectral_utilities - use mesh + use mesh_grid use thermal_conduction use material use numerics @@ -203,8 +203,9 @@ end function grid_thermal_spectral_solution !-------------------------------------------------------------------------------------------------- !> @brief forwarding routine !-------------------------------------------------------------------------------------------------- -subroutine grid_thermal_spectral_forward +subroutine grid_thermal_spectral_forward(cutBack) + logical, intent(in) :: cutBack integer :: i, j, k, cell DM :: dm_local PetscScalar, dimension(:,:,:), pointer :: x_scal diff --git a/src/grid/spectral_utilities.f90 b/src/grid/spectral_utilities.f90 index aeaf748c3..a1265556a 100644 --- a/src/grid/spectral_utilities.f90 +++ b/src/grid/spectral_utilities.f90 @@ -10,8 +10,9 @@ module spectral_utilities use prec use math + use rotations use IO - use mesh + use mesh_grid use numerics use debug use config @@ -22,11 +23,7 @@ module spectral_utilities private include 'fftw3-mpi.f03' - - logical, public :: cutBack = .false. !< cut back of BVP solver in case convergence is not achieved or a material point is terminally ill - integer, public, parameter :: maxPhaseFields = 2 - integer, public :: nActiveFields = 0 - + !-------------------------------------------------------------------------------------------------- ! field labels information enum, bind(c) @@ -39,11 +36,13 @@ module spectral_utilities !-------------------------------------------------------------------------------------------------- ! grid related information information - real(pReal), public :: wgt !< weighting factor 1/Nelems + real(pReal), protected, public :: wgt !< weighting factor 1/Nelems + integer, protected, public :: grid1Red !< grid(1)/2 + real(pReal), protected, public, dimension(3) :: scaledGeomSize !< scaled geometry size for calculation of divergence !-------------------------------------------------------------------------------------------------- ! variables storing information for spectral method and FFTW - integer, public :: grid1Red !< grid(1)/2 + real (C_DOUBLE), public, dimension(:,:,:,:,:), pointer :: tensorField_real !< real representation (some stress or deformation) of field_fourier complex(C_DOUBLE_COMPLEX),public, dimension(:,:,:,:,:), pointer :: tensorField_fourier !< field on which the Fourier transform operates real(C_DOUBLE), public, dimension(:,:,:,:), pointer :: vectorField_real !< vector field real representation for fftw @@ -54,7 +53,7 @@ module spectral_utilities complex(pReal), private, dimension(:,:,:,:), allocatable :: xi1st !< wave vector field for first derivatives complex(pReal), private, dimension(:,:,:,:), allocatable :: xi2nd !< wave vector field for second derivatives real(pReal), private, dimension(3,3,3,3) :: C_ref !< mechanic reference stiffness - real(pReal), protected, public, dimension(3) :: scaledGeomSize !< scaled geometry size for calculation of divergence (Basic, Basic PETSc) + !-------------------------------------------------------------------------------------------------- ! plans for FFTW @@ -92,7 +91,7 @@ module spectral_utilities end type tBoundaryCondition type, public :: tLoadCase - real(pReal), dimension (3,3) :: rotation = math_I3 !< rotation of BC + type(rotation) :: rot !< rotation of BC type(tBoundaryCondition) :: stress, & !< stress BC deformation !< deformation BC (Fdot or L) real(pReal) :: time = 0.0_pReal !< length of increment @@ -105,7 +104,8 @@ module spectral_utilities end type tLoadCase type, public :: tSolutionParams !< @todo use here the type definition for a full loadcase - real(pReal), dimension(3,3) :: stress_mask, stress_BC, rotation_BC + real(pReal), dimension(3,3) :: stress_mask, stress_BC + type(rotation) :: rotation_BC real(pReal) :: timeinc real(pReal) :: timeincOld end type tSolutionParams @@ -157,13 +157,12 @@ module spectral_utilities utilities_constitutiveResponse, & utilities_calculateRate, & utilities_forwardField, & - utilities_updateIPcoords, & + utilities_updateCoords, & + utilities_saveReferenceStiffness, & FIELD_UNDEFINED_ID, & FIELD_MECH_ID, & FIELD_THERMAL_ID, & FIELD_DAMAGE_ID - private :: & - utilities_getFreqDerivative contains @@ -390,27 +389,18 @@ end subroutine utilities_init !> @details Sets the current reference stiffness to the stiffness given as an argument. !> If the gamma operator is precalculated, it is calculated with this stiffness. !> In case of an on-the-fly calculation, only the reference stiffness is updated. -!> Also writes out the current reference stiffness for restart. !--------------------------------------------------------------------------------------------------- -subroutine utilities_updateGamma(C,saveReference) +subroutine utilities_updateGamma(C) real(pReal), intent(in), dimension(3,3,3,3) :: C !< input stiffness to store as reference stiffness - logical , intent(in) :: saveReference !< save reference stiffness to file for restart complex(pReal), dimension(3,3) :: temp33_complex, xiDyad_cmplx real(pReal), dimension(6,6) :: A, A_inv integer :: & i, j, k, & - l, m, n, o, & - fileUnit + l, m, n, o logical :: err C_ref = C - if (saveReference .and. worldrank == 0) then - write(6,'(/,a)') ' writing reference stiffness to file' - flush(6) - fileUnit = IO_open_jobFile_binary('C_ref','w') - write(fileUnit) C_ref; close(fileUnit) - endif if(.not. num%memory_efficient) then gamma_hat = cmplx(0.0_pReal,0.0_pReal,pReal) ! for the singular point and any non invertible A @@ -438,10 +428,12 @@ end subroutine utilities_updateGamma !-------------------------------------------------------------------------------------------------- !> @brief forward FFT of data in field_real to field_fourier -!> @details Does an unweighted filtered FFT transform from real to complex +!> @details Does an unweighted FFT transform from real to complex. Extra padding entries are set +! to 0.0 !-------------------------------------------------------------------------------------------------- subroutine utilities_FFTtensorForward + tensorField_real(1:3,1:3,grid(1)+1:grid1Red*2,:,:) = cmplx(0.0,0.0,pReal) call fftw_mpi_execute_dft_r2c(planTensorForth,tensorField_real,tensorField_fourier) end subroutine utilities_FFTtensorForward @@ -460,10 +452,12 @@ end subroutine utilities_FFTtensorBackward !-------------------------------------------------------------------------------------------------- !> @brief forward FFT of data in scalarField_real to scalarField_fourier -!> @details Does an unweighted filtered FFT transform from real to complex +!> @details Does an unweighted FFT transform from real to complex. Extra padding entries are set +! to 0.0 !-------------------------------------------------------------------------------------------------- subroutine utilities_FFTscalarForward + scalarField_real(grid(1)+1:grid1Red*2,:,:) = cmplx(0.0,0.0,pReal) call fftw_mpi_execute_dft_r2c(planScalarForth,scalarField_real,scalarField_fourier) end subroutine utilities_FFTscalarForward @@ -483,10 +477,12 @@ end subroutine utilities_FFTscalarBackward !-------------------------------------------------------------------------------------------------- !> @brief forward FFT of data in field_real to field_fourier with highest freqs. removed -!> @details Does an unweighted filtered FFT transform from real to complex. +!> @details Does an unweighted FFT transform from real to complex. Extra padding entries are set +! to 0.0 !-------------------------------------------------------------------------------------------------- subroutine utilities_FFTvectorForward + vectorField_real(1:3,grid(1)+1:grid1Red*2,:,:) = cmplx(0.0,0.0,pReal) call fftw_mpi_execute_dft_r2c(planVectorForth,vectorField_real,vectorField_fourier) end subroutine utilities_FFTvectorForward @@ -690,10 +686,11 @@ end function utilities_curlRMS !-------------------------------------------------------------------------------------------------- function utilities_maskedCompliance(rot_BC,mask_stress,C) - real(pReal), dimension(3,3,3,3) :: utilities_maskedCompliance !< masked compliance - real(pReal), intent(in) , dimension(3,3,3,3) :: C !< current average stiffness - real(pReal), intent(in) , dimension(3,3) :: rot_BC !< rotation of load frame - logical, intent(in), dimension(3,3) :: mask_stress !< mask of stress BC + real(pReal), dimension(3,3,3,3) :: utilities_maskedCompliance !< masked compliance + real(pReal), intent(in), dimension(3,3,3,3) :: C !< current average stiffness + type(rotation), intent(in) :: rot_BC !< rotation of load frame + logical, intent(in), dimension(3,3) :: mask_stress !< mask of stress BC + integer :: j, k, m, n logical, dimension(9) :: mask_stressVector real(pReal), dimension(9,9) :: temp99_Real @@ -711,7 +708,7 @@ function utilities_maskedCompliance(rot_BC,mask_stress,C) allocate (c_reduced(size_reduced,size_reduced), source =0.0_pReal) allocate (s_reduced(size_reduced,size_reduced), source =0.0_pReal) allocate (sTimesC(size_reduced,size_reduced), source =0.0_pReal) - temp99_Real = math_3333to99(math_rotate_forward3333(C,rot_BC)) + temp99_Real = math_3333to99(rot_BC%rotTensor4(C)) if(debugGeneral) then write(6,'(/,a)') ' ... updating masked compliance ............................................' @@ -783,10 +780,10 @@ subroutine utilities_fourierScalarGradient() integer :: i, j, k - vectorField_fourier = cmplx(0.0_pReal,0.0_pReal,pReal) - forall(k = 1:grid3, j = 1:grid(2), i = 1:grid1Red) & - vectorField_fourier(1:3,i,j,k) = scalarField_fourier(i,j,k)*xi1st(1:3,i,j,k) - + do k = 1, grid3; do j = 1, grid(2); do i = 1,grid1Red + vectorField_fourier(1:3,i,j,k) = scalarField_fourier(i,j,k)*xi1st(1:3,i,j,k) ! ToDo: no -conjg? + enddo; enddo; enddo + end subroutine utilities_fourierScalarGradient @@ -795,13 +792,12 @@ end subroutine utilities_fourierScalarGradient !-------------------------------------------------------------------------------------------------- subroutine utilities_fourierVectorDivergence() - integer :: i, j, k - - scalarField_fourier = cmplx(0.0_pReal,0.0_pReal,pReal) - forall(k = 1:grid3, j = 1:grid(2), i = 1:grid1Red) & - scalarField_fourier(i,j,k) = scalarField_fourier(i,j,k) & - + sum(vectorField_fourier(1:3,i,j,k)*conjg(-xi1st(1:3,i,j,k))) + integer :: i, j, k + do k = 1, grid3; do j = 1, grid(2); do i = 1,grid1Red + scalarField_fourier(i,j,k) = sum(vectorField_fourier(1:3,i,j,k)*conjg(-xi1st(1:3,i,j,k))) + enddo; enddo; enddo + end subroutine utilities_fourierVectorDivergence @@ -812,7 +808,6 @@ subroutine utilities_fourierVectorGradient() integer :: i, j, k, m, n - tensorField_fourier = cmplx(0.0_pReal,0.0_pReal,pReal) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid1Red do m = 1, 3; do n = 1, 3 tensorField_fourier(m,n,i,j,k) = vectorField_fourier(m,i,j,k)*xi1st(n,i,j,k) @@ -827,14 +822,10 @@ end subroutine utilities_fourierVectorGradient !-------------------------------------------------------------------------------------------------- subroutine utilities_fourierTensorDivergence() - integer :: i, j, k, m, n + integer :: i, j, k - vectorField_fourier = cmplx(0.0_pReal,0.0_pReal,pReal) do k = 1, grid3; do j = 1, grid(2); do i = 1,grid1Red - do m = 1, 3; do n = 1, 3 - vectorField_fourier(m,i,j,k) = vectorField_fourier(m,i,j,k) & - + tensorField_fourier(m,n,i,j,k)*conjg(-xi1st(n,i,j,k)) - enddo; enddo + vectorField_fourier(:,i,j,k) = matmul(tensorField_fourier(:,:,i,j,k),conjg(-xi1st(:,i,j,k))) enddo; enddo; enddo end subroutine utilities_fourierTensorDivergence @@ -846,12 +837,12 @@ end subroutine utilities_fourierTensorDivergence subroutine utilities_constitutiveResponse(P,P_av,C_volAvg,C_minmaxAvg,& F,timeinc,rotation_BC) - real(pReal),intent(out), dimension(3,3,3,3) :: C_volAvg, C_minmaxAvg !< average stiffness - real(pReal),intent(out), dimension(3,3) :: P_av !< average PK stress - real(pReal),intent(out), dimension(3,3,grid(1),grid(2),grid3) :: P !< PK stress - real(pReal), intent(in), dimension(3,3,grid(1),grid(2),grid3) :: F !< deformation gradient target - real(pReal), intent(in) :: timeinc !< loading time - real(pReal), intent(in), dimension(3,3) :: rotation_BC !< rotation of load frame + real(pReal), intent(out), dimension(3,3,3,3) :: C_volAvg, C_minmaxAvg !< average stiffness + real(pReal), intent(out), dimension(3,3) :: P_av !< average PK stress + real(pReal), intent(out), dimension(3,3,grid(1),grid(2),grid3) :: P !< PK stress + real(pReal), intent(in), dimension(3,3,grid(1),grid(2),grid3) :: F !< deformation gradient target + real(pReal), intent(in) :: timeinc !< loading time + type(rotation), intent(in), optional :: rotation_BC !< rotation of load frame integer :: & @@ -873,7 +864,8 @@ subroutine utilities_constitutiveResponse(P,P_av,C_volAvg,C_minmaxAvg,& if (debugRotation) & write(6,'(/,a,/,3(3(2x,f12.4,1x)/))',advance='no') ' Piola--Kirchhoff stress (lab) / MPa =',& transpose(P_av)*1.e-6_pReal - P_av = math_rotate_forward33(P_av,rotation_BC) + if(present(rotation_BC)) & + P_av = rotation_BC%rotTensor2(P_av) write(6,'(/,a,/,3(3(2x,f12.4,1x)/))',advance='no') ' Piola--Kirchhoff stress / MPa =',& transpose(P_av)*1.e-6_pReal flush(6) @@ -1024,51 +1016,119 @@ end function utilities_getFreqDerivative ! using integration in Fourier space. Similar as in mesh.f90, but using data already defined for ! convolution !-------------------------------------------------------------------------------------------------- -subroutine utilities_updateIPcoords(F) +subroutine utilities_updateCoords(F) real(pReal), dimension(3,3,grid(1),grid(2),grid3), intent(in) :: F - integer :: i, j, k, m, ierr - real(pReal), dimension(3) :: step, offset_coords + real(pReal), dimension(3, grid(1),grid(2),grid3) :: IPcoords + real(pReal), dimension(3, grid(1),grid(2),grid3+2) :: IPfluct_padded ! Fluctuations of cell center displacement (padded along z for MPI) + real(pReal), dimension(3, grid(1)+1,grid(2)+1,grid3+1) :: nodeCoords + integer :: & + i,j,k,n, & + rank_t, & + rank_b, & + c, r, & + ierr + integer, dimension(MPI_STATUS_SIZE) :: & + s + real(pReal), dimension(3) :: step real(pReal), dimension(3,3) :: Favg + integer, dimension(3) :: me + integer, dimension(3,8) :: & + neighbor = reshape([ & + 0, 0, 0, & + 1, 0, 0, & + 1, 1, 0, & + 0, 1, 0, & + 0, 0, 1, & + 1, 0, 1, & + 1, 1, 1, & + 0, 1, 1 ], [3,8]) + step = geomSize/real(grid, pReal) !-------------------------------------------------------------------------------------------------- - ! integration in Fourier space - tensorField_real = 0.0_pReal + ! integration in Fourier space to get fluctuations of cell center discplacements tensorField_real(1:3,1:3,1:grid(1),1:grid(2),1:grid3) = F call utilities_FFTtensorForward() - call utilities_fourierTensorDivergence() - + do k = 1, grid3; do j = 1, grid(2); do i = 1, grid1Red - if (any(cNeq(xi1st(1:3,i,j,k),cmplx(0.0,0.0,pReal)))) & - vectorField_fourier(1:3,i,j,k) = vectorField_fourier(1:3,i,j,k)/ & - sum(conjg(-xi1st(1:3,i,j,k))*xi1st(1:3,i,j,k)) + if(any([i,j,k+grid3Offset] /= 1)) then + vectorField_fourier(1:3,i,j,k) = matmul(tensorField_fourier(1:3,1:3,i,j,k),xi2nd(1:3,i,j,k)) & + / sum(conjg(-xi2nd(1:3,i,j,k))*xi2nd(1:3,i,j,k)) * wgt + else + vectorField_fourier(1:3,i,j,k) = cmplx(0.0,0.0,pReal) + endif enddo; enddo; enddo + call fftw_mpi_execute_dft_c2r(planVectorBack,vectorField_fourier,vectorField_real) - vectorField_real = vectorField_real * wgt !-------------------------------------------------------------------------------------------------- ! average F if (grid3Offset == 0) Favg = real(tensorField_fourier(1:3,1:3,1,1,1),pReal)*wgt call MPI_Bcast(Favg,9,MPI_DOUBLE,0,PETSC_COMM_WORLD,ierr) - if(ierr /=0) call IO_error(894, ext_msg='update_IPcoords') - + if(ierr /=0) call IO_error(894, ext_msg='update_IPcoords/MPI_Bcast') + !-------------------------------------------------------------------------------------------------- - ! add average to fluctuation and put (0,0,0) on (0,0,0) - step = geomSize/real(grid, pReal) - if (grid3Offset == 0) offset_coords = vectorField_real(1:3,1,1,1) - call MPI_Bcast(offset_coords,3,MPI_DOUBLE,0,PETSC_COMM_WORLD,ierr) - if(ierr /=0) call IO_error(894, ext_msg='update_IPcoords') - offset_coords = matmul(Favg,step/2.0_pReal) - offset_coords - m = 1 + ! pad cell center fluctuations along z-direction (needed when running MPI simulation) + IPfluct_padded(1:3,1:grid(1),1:grid(2),2:grid3+1) = vectorField_real(1:3,1:grid(1),1:grid(2),1:grid3) + c = product(shape(IPfluct_padded(:,:,:,1))) !< amount of data to transfer + rank_t = modulo(worldrank+1,worldsize) + rank_b = modulo(worldrank-1,worldsize) + + ! send bottom layer to process below + call MPI_Isend(IPfluct_padded(:,:,:,2), c,MPI_DOUBLE,rank_b,0,PETSC_COMM_WORLD,r,ierr) + if(ierr /=0) call IO_error(894, ext_msg='update_IPcoords/MPI_Isend') + call MPI_Irecv(IPfluct_padded(:,:,:,grid3+2),c,MPI_DOUBLE,rank_t,0,PETSC_COMM_WORLD,r,ierr) + if(ierr /=0) call IO_error(894, ext_msg='update_IPcoords/MPI_Irecv') + call MPI_Wait(r,s,ierr) + + ! send top layer to process above + if(ierr /=0) call IO_error(894, ext_msg='update_IPcoords/MPI_Wait') + call MPI_Isend(IPfluct_padded(:,:,:,grid3+1),c,MPI_DOUBLE,rank_t,0,PETSC_COMM_WORLD,r,ierr) + if(ierr /=0) call IO_error(894, ext_msg='update_IPcoords/MPI_Isend') + call MPI_Irecv(IPfluct_padded(:,:,:,1), c,MPI_DOUBLE,rank_b,0,PETSC_COMM_WORLD,r,ierr) + if(ierr /=0) call IO_error(894, ext_msg='update_IPcoords/MPI_Irecv') + call MPI_Wait(r,s,ierr) + + !-------------------------------------------------------------------------------------------------- + ! calculate nodal displacements + nodeCoords = 0.0_pReal + do k = 0,grid3; do j = 0,grid(2); do i = 0,grid(1) + nodeCoords(1:3,i+1,j+1,k+1) = matmul(Favg,step*(real([i,j,k+grid3Offset],pReal))) + averageFluct: do n = 1,8 + me = [i+neighbor(1,n),j+neighbor(2,n),k+neighbor(3,n)] + nodeCoords(1:3,i+1,j+1,k+1) = nodeCoords(1:3,i+1,j+1,k+1) & + + IPfluct_padded(1:3,modulo(me(1)-1,grid(1))+1,modulo(me(2)-1,grid(2))+1,me(3)+1)*0.125_pReal + enddo averageFluct + enddo; enddo; enddo + + !-------------------------------------------------------------------------------------------------- + ! calculate cell center displacements do k = 1,grid3; do j = 1,grid(2); do i = 1,grid(1) - mesh_ipCoordinates(1:3,1,m) = vectorField_real(1:3,i,j,k) & - + offset_coords & - + matmul(Favg,step*real([i,j,k+grid3Offset]-1,pReal)) - m = m+1 + IPcoords(1:3,i,j,k) = vectorField_real(1:3,i,j,k) & + + matmul(Favg,step*real([i,j,k+grid3Offset]-0.5_pReal,pReal)) enddo; enddo; enddo - call discretization_setIPcoords(reshape(mesh_ipCoordinates,[3,grid(1)*grid(2)*grid3])) + call discretization_setNodeCoords(reshape(NodeCoords,[3,(grid(1)+1)*(grid(2)+1)*(grid3+1)])) + call discretization_setIPcoords (reshape(IPcoords, [3,grid(1)*grid(2)*grid3])) + +end subroutine utilities_updateCoords -end subroutine utilities_updateIPcoords + +!--------------------------------------------------------------------------------------------------- +!> @brief Write out the current reference stiffness for restart. +!--------------------------------------------------------------------------------------------------- +subroutine utilities_saveReferenceStiffness + + integer :: & + fileUnit + + if (worldrank == 0) then + write(6,'(a)') ' writing reference stiffness data required for restart to file';flush(6) + fileUnit = IO_open_jobFile_binary('C_ref','w') + write(fileUnit) C_ref + close(fileUnit) + endif + +end subroutine utilities_saveReferenceStiffness end module spectral_utilities diff --git a/src/homogenization.f90 b/src/homogenization.f90 index c7675ccba..0112f9cf5 100644 --- a/src/homogenization.f90 +++ b/src/homogenization.f90 @@ -15,7 +15,6 @@ module homogenization use constitutive use crystallite use FEsolving - use mesh use discretization use thermal_isothermal use thermal_adiabatic @@ -256,16 +255,15 @@ subroutine homogenization_init thermal_maxSizePostResults = 0 damage_maxSizePostResults = 0 do p = 1,size(config_homogenization) - thermal_maxSizePostResults = max(thermal_maxSizePostResults, thermalState (p)%sizePostResults) - damage_maxSizePostResults = max(damage_maxSizePostResults ,damageState (p)%sizePostResults) + thermal_maxSizePostResults = max(thermal_maxSizePostResults, thermalState(p)%sizePostResults) + damage_maxSizePostResults = max(damage_maxSizePostResults, damageState (p)%sizePostResults) enddo materialpoint_sizeResults = 1 & ! grain count + 1 + thermal_maxSizePostResults & + damage_maxSizePostResults & - + homogenization_maxNgrains * (1 + crystallite_maxSizePostResults & ! crystallite size & crystallite results - + 1 + constitutive_plasticity_maxSizePostResults & ! constitutive size & constitutive results - + constitutive_source_maxSizePostResults) + + homogenization_maxNgrains * ( 1 & ! crystallite size + + 1 + constitutive_source_maxSizePostResults) allocate(materialpoint_results(materialpoint_sizeResults,discretization_nIP,discretization_nElem)) write(6,'(/,a)') ' <<<+- homogenization init -+>>>' @@ -593,15 +591,13 @@ subroutine materialpoint_postResults thePos, & theSize, & myNgrains, & - myCrystallite, & g, & !< grain number i, & !< integration point number e !< element number - !$OMP PARALLEL DO PRIVATE(myNgrains,myCrystallite,thePos,theSize) + !$OMP PARALLEL DO PRIVATE(myNgrains,thePos,theSize) elementLooping: do e = FEsolving_execElem(1),FEsolving_execElem(2) myNgrains = homogenization_Ngrains(material_homogenizationAt(e)) - myCrystallite = microstructure_crystallite(discretization_microstructureAt(e)) IpLooping: do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) thePos = 0 @@ -619,9 +615,9 @@ subroutine materialpoint_postResults thePos = thePos + 1 grainLooping :do g = 1,myNgrains - theSize = 1 + crystallite_sizePostResults(myCrystallite) + & - 1 + plasticState (material_phaseAt(g,e))%sizePostResults + & - sum(sourceState(material_phaseAt(g,e))%p(:)%sizePostResults) + theSize = 1 + & + 1 + & + sum(sourceState(material_phaseAt(g,e))%p(:)%sizePostResults) materialpoint_results(thePos+1:thePos+theSize,i,e) = crystallite_postResults(g,i,e) ! tell crystallite results thePos = thePos + theSize enddo grainLooping diff --git a/src/homogenization_mech_RGC.f90 b/src/homogenization_mech_RGC.f90 index 0ae0f4c18..61a1997cd 100644 --- a/src/homogenization_mech_RGC.f90 +++ b/src/homogenization_mech_RGC.f90 @@ -160,7 +160,6 @@ module subroutine mech_RGC_init + size(['avg constitutive work ','average penalty energy']) homogState(h)%sizeState = sizeState - homogState(h)%sizePostResults = 0 allocate(homogState(h)%state0 (sizeState,NofMyHomog), source=0.0_pReal) allocate(homogState(h)%subState0(sizeState,NofMyHomog), source=0.0_pReal) allocate(homogState(h)%state (sizeState,NofMyHomog), source=0.0_pReal) diff --git a/src/homogenization_mech_isostrain.f90 b/src/homogenization_mech_isostrain.f90 index c1eba821c..cdc078925 100644 --- a/src/homogenization_mech_isostrain.f90 +++ b/src/homogenization_mech_isostrain.f90 @@ -63,7 +63,6 @@ module subroutine mech_isostrain_init NofMyHomog = count(material_homogenizationAt == h) homogState(h)%sizeState = 0 - homogState(h)%sizePostResults = 0 allocate(homogState(h)%state0 (0,NofMyHomog)) allocate(homogState(h)%subState0(0,NofMyHomog)) allocate(homogState(h)%state (0,NofMyHomog)) diff --git a/src/homogenization_mech_none.f90 b/src/homogenization_mech_none.f90 index d5b24e5d1..3e7998d88 100644 --- a/src/homogenization_mech_none.f90 +++ b/src/homogenization_mech_none.f90 @@ -29,7 +29,6 @@ module subroutine mech_none_init NofMyHomog = count(material_homogenizationAt == h) homogState(h)%sizeState = 0 - homogState(h)%sizePostResults = 0 allocate(homogState(h)%state0 (0,NofMyHomog)) allocate(homogState(h)%subState0(0,NofMyHomog)) allocate(homogState(h)%state (0,NofMyHomog)) diff --git a/src/material.f90 b/src/material.f90 index 68f71ea2a..8aeab5dec 100644 --- a/src/material.f90 +++ b/src/material.f90 @@ -11,7 +11,6 @@ module material use results use IO use debug - use mesh use numerics use rotations use discretization @@ -117,13 +116,11 @@ module material phase_Noutput, & !< number of '(output)' items per phase phase_elasticityInstance, & !< instance of particular elasticity of each phase phase_plasticityInstance, & !< instance of particular plasticity of each phase - crystallite_Noutput, & !< number of '(output)' items per crystallite setting homogenization_Ngrains, & !< number of grains in each homogenization homogenization_Noutput, & !< number of '(output)' items per homogenization homogenization_typeInstance, & !< instance of particular type of each homogenization thermal_typeInstance, & !< instance of particular type of each thermal transport - damage_typeInstance, & !< instance of particular type of each nonlocal damage - microstructure_crystallite !< crystallite setting ID of each microstructure ! DEPRECATED !!!! + damage_typeInstance !< instance of particular type of each nonlocal damage real(pReal), dimension(:), allocatable, public, protected :: & thermal_initialT, & !< initial temperature per each homogenization @@ -136,7 +133,7 @@ module material material_homogenizationMemberAt !< position of the element within its homogenization instance integer, dimension(:,:), allocatable, public, protected :: & ! (constituent,elem) material_phaseAt !< phase ID of each element - integer, dimension(:,:,:), allocatable, public, protected :: & ! (constituent,ip,elem) + integer, dimension(:,:,:), allocatable, public, protected :: & ! (constituent,elem) material_phaseMemberAt !< position of the element within its phase instance ! END NEW MAPPINGS @@ -246,9 +243,6 @@ subroutine material_init call material_parseMicrostructure() if (iand(myDebug,debug_levelBasic) /= 0) write(6,'(a)') ' Microstructure parsed'; flush(6) - call material_parseCrystallite() - if (iand(myDebug,debug_levelBasic) /= 0) write(6,'(a)') ' Crystallite parsed'; flush(6) - call material_parseHomogenization() if (iand(myDebug,debug_levelBasic) /= 0) write(6,'(a)') ' Homogenization parsed'; flush(6) @@ -278,9 +272,6 @@ subroutine material_init allocate(temperatureRate (material_Nhomogenization)) do m = 1,size(config_microstructure) - if(microstructure_crystallite(m) < 1 .or. & - microstructure_crystallite(m) > size(config_crystallite)) & - call IO_error(150,m,ext_msg='crystallite') if(minval(microstructure_phase(1:microstructure_Nconstituents(m),m)) < 1 .or. & maxval(microstructure_phase(1:microstructure_Nconstituents(m),m)) > size(config_phase)) & call IO_error(150,m,ext_msg='phase') @@ -299,9 +290,8 @@ subroutine material_init enddo write(6,'(/,a14,18x,1x,a11,1x,a12,1x,a13)') 'microstructure','crystallite','constituents' do m = 1,size(config_microstructure) - write(6,'(1x,a32,1x,i11,1x,i12)') config_name_microstructure(m), & - microstructure_crystallite(m), & - microstructure_Nconstituents(m) + write(6,'(1x,a32,1x,i12)') config_name_microstructure(m), & + microstructure_Nconstituents(m) if (microstructure_Nconstituents(m) > 0) then do c = 1,microstructure_Nconstituents(m) write(6,'(a1,1x,a32,1x,a32,1x,f7.4)') '>',config_name_phase(microstructure_phase(c,m)),& @@ -501,7 +491,6 @@ subroutine material_parseMicrostructure character(len=65536) :: & tag - allocate(microstructure_crystallite(size(config_microstructure)), source=0) allocate(microstructure_Nconstituents(size(config_microstructure)), source=0) allocate(microstructure_active(size(config_microstructure)), source=.false.) @@ -513,7 +502,6 @@ subroutine material_parseMicrostructure do m=1, size(config_microstructure) microstructure_Nconstituents(m) = config_microstructure(m)%countKeys('(constituent)') - microstructure_crystallite(m) = config_microstructure(m)%getInt('crystallite') enddo microstructure_maxNconstituents = maxval(microstructure_Nconstituents) @@ -548,21 +536,6 @@ subroutine material_parseMicrostructure end subroutine material_parseMicrostructure -!-------------------------------------------------------------------------------------------------- -!> @brief parses the crystallite part in the material configuration file -!-------------------------------------------------------------------------------------------------- -subroutine material_parseCrystallite - - integer :: c - - allocate(crystallite_Noutput(size(config_crystallite)),source=0) - do c=1, size(config_crystallite) - crystallite_Noutput(c) = config_crystallite(c)%countKeys('(output)') - enddo - -end subroutine material_parseCrystallite - - !-------------------------------------------------------------------------------------------------- !> @brief parses the phase part in the material configuration file !-------------------------------------------------------------------------------------------------- @@ -776,9 +749,6 @@ subroutine material_allocatePlasticState(phase,NofMyPhase,& plasticState(phase)%sizeDotState = sizeDotState plasticState(phase)%sizeDeltaState = sizeDeltaState plasticState(phase)%offsetDeltaState = sizeState-sizeDeltaState ! deltaState occupies latter part of state by definition - plasticState(phase)%Nslip = Nslip - plasticState(phase)%Ntwin = Ntwin - plasticState(phase)%Ntrans= Ntrans allocate(plasticState(phase)%aTolState (sizeState), source=0.0_pReal) allocate(plasticState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) diff --git a/src/math.f90 b/src/math.f90 index 5a3a5f467..0b06c9186 100644 --- a/src/math.f90 +++ b/src/math.f90 @@ -838,32 +838,6 @@ pure function math_Voigt66to3333(m66) end function math_Voigt66to3333 -!-------------------------------------------------------------------------------------------------- -!> @brief action of a quaternion on a vector (rotate vector v with Q) -!-------------------------------------------------------------------------------------------------- -pure function math_qRot(Q,v) - - real(pReal), dimension(4), intent(in) :: Q - real(pReal), dimension(3), intent(in) :: v - real(pReal), dimension(3) :: math_qRot - real(pReal), dimension(4,4) :: T - integer :: i, j - - do i = 1,4 - do j = 1,i - T(i,j) = Q(i) * Q(j) - enddo - enddo - - math_qRot = [-v(1)*(T(3,3)+T(4,4)) + v(2)*(T(3,2)-T(4,1)) + v(3)*(T(4,2)+T(3,1)), & - v(1)*(T(3,2)+T(4,1)) - v(2)*(T(2,2)+T(4,4)) + v(3)*(T(4,3)-T(2,1)), & - v(1)*(T(4,2)-T(3,1)) + v(2)*(T(4,3)+T(2,1)) - v(3)*(T(2,2)+T(3,3))] - - math_qRot = 2.0_pReal * math_qRot + v - -end function math_qRot - - !-------------------------------------------------------------------------------------------------- !> @brief rotation matrix from Bunge-Euler (3-1-3) angles (in radians) !> @details deprecated @@ -1327,52 +1301,6 @@ real(pReal) pure function math_areaTriangle(v1,v2,v3) end function math_areaTriangle -!-------------------------------------------------------------------------------------------------- -!> @brief rotate 33 tensor forward -!-------------------------------------------------------------------------------------------------- -pure function math_rotate_forward33(tensor,R) - - real(pReal), dimension(3,3) :: math_rotate_forward33 - real(pReal), dimension(3,3), intent(in) :: tensor, R - - math_rotate_forward33 = matmul(R,matmul(tensor,transpose(R))) - -end function math_rotate_forward33 - - -!-------------------------------------------------------------------------------------------------- -!> @brief rotate 33 tensor backward -!-------------------------------------------------------------------------------------------------- -pure function math_rotate_backward33(tensor,R) - - real(pReal), dimension(3,3) :: math_rotate_backward33 - real(pReal), dimension(3,3), intent(in) :: tensor, R - - math_rotate_backward33 = matmul(transpose(R),matmul(tensor,R)) - -end function math_rotate_backward33 - - -!-------------------------------------------------------------------------------------------------- -!> @brief rotate 3333 tensor C'_ijkl=g_im*g_jn*g_ko*g_lp*C_mnop -!-------------------------------------------------------------------------------------------------- -pure function math_rotate_forward3333(tensor,R) - - real(pReal), dimension(3,3,3,3) :: math_rotate_forward3333 - real(pReal), dimension(3,3), intent(in) :: R - real(pReal), dimension(3,3,3,3), intent(in) :: tensor - integer :: i,j,k,l,m,n,o,p - - math_rotate_forward3333 = 0.0_pReal - do i = 1,3;do j = 1,3;do k = 1,3;do l = 1,3 - do m = 1,3;do n = 1,3;do o = 1,3;do p = 1,3 - math_rotate_forward3333(i,j,k,l) = math_rotate_forward3333(i,j,k,l) & - + R(i,m) * R(j,n) * R(k,o) * R(l,p) * tensor(m,n,o,p) - enddo; enddo; enddo; enddo; enddo; enddo; enddo; enddo - -end function math_rotate_forward3333 - - !-------------------------------------------------------------------------------------------------- !> @brief limits a scalar value to a certain range (either one or two sided) ! Will return NaN if left > right diff --git a/src/mesh/DAMASK_FEM.f90 b/src/mesh/DAMASK_FEM.f90 index 3602bd068..3d4c332a0 100644 --- a/src/mesh/DAMASK_FEM.f90 +++ b/src/mesh/DAMASK_FEM.f90 @@ -3,7 +3,7 @@ !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief Driver controlling inner and outer load case looping of the FEM solver -!> @details doing cutbacking, forwarding in case of restart, reporting statistics, writing +!> @details doing cutbacking, reporting statistics, writing !> results !-------------------------------------------------------------------------------------------------- program DAMASK_FEM @@ -53,12 +53,9 @@ program DAMASK_FEM currentFace = 0, & inc, & !< current increment in current load case totalIncsCounter = 0, & !< total # of increments - convergedCounter = 0, & !< # of converged increments - notConvergedCounter = 0, & !< # of non-converged increments fileUnit = 0, & !< file unit for reading load case and writing results myStat, & statUnit = 0, & !< file unit for statistics output - lastRestartWritten = 0, & !< total increment No. at which last restart information was written stagIter, & component character(len=6) :: loadcase_string @@ -164,9 +161,6 @@ program DAMASK_FEM loadCases(currentLoadCase)%logscale = 1 case('freq','frequency','outputfreq') ! frequency of result writings loadCases(currentLoadCase)%outputfrequency = IO_intValue(line,chunkPos,i+1) - case('r','restart','restartwrite') ! frequency of writing restart information - loadCases(currentLoadCase)%restartfrequency = & - max(0,IO_intValue(line,chunkPos,i+1)) case('guessreset','dropguessing') loadCases(currentLoadCase)%followFormerTrajectory = .false. ! do not continue to predict deformation along former trajectory @@ -246,8 +240,6 @@ program DAMASK_FEM if (loadCases(currentLoadCase)%outputfrequency < 1) errorID = 836 ! non-positive result frequency write(6,'(2x,a,i5)') 'output frequency: ', & loadCases(currentLoadCase)%outputfrequency - write(6,'(2x,a,i5,/)') 'restart frequency: ', & - loadCases(currentLoadCase)%restartfrequency if (errorID > 0) call IO_error(error_ID = errorID, ext_msg = loadcase_string) ! exit with error message enddo checkLoadcases @@ -293,117 +285,106 @@ program DAMASK_FEM endif timeinc = timeinc * real(subStepFactor,pReal)**real(-cutBackLevel,pReal) ! depending on cut back level, decrease time step - skipping: if (totalIncsCounter <= interface_restartInc) then ! not yet at restart inc? - time = time + timeinc ! just advance time, skip already performed calculation - guess = .true. - else skipping - stepFraction = 0 ! fraction scaled by stepFactor**cutLevel - subStepLooping: do while (stepFraction < subStepFactor**cutBackLevel) - remainingLoadCaseTime = loadCases(currentLoadCase)%time+time0 - time - time = time + timeinc ! forward target time - stepFraction = stepFraction + 1 ! count step - + stepFraction = 0 ! fraction scaled by stepFactor**cutLevel + + subStepLooping: do while (stepFraction < subStepFactor**cutBackLevel) + remainingLoadCaseTime = loadCases(currentLoadCase)%time+time0 - time + time = time + timeinc ! forward target time + stepFraction = stepFraction + 1 ! count step + !-------------------------------------------------------------------------------------------------- ! report begin of new step - write(6,'(/,a)') ' ###########################################################################' - write(6,'(1x,a,es12.5'//& - ',a,'//IO_intOut(inc)//',a,'//IO_intOut(loadCases(currentLoadCase)%incs)//& - ',a,'//IO_intOut(stepFraction)//',a,'//IO_intOut(subStepFactor**cutBackLevel)//& - ',a,'//IO_intOut(currentLoadCase)//',a,'//IO_intOut(size(loadCases))//')') & - 'Time', time, & - 's: Increment ', inc, '/', loadCases(currentLoadCase)%incs,& - '-', stepFraction, '/', subStepFactor**cutBackLevel,& - ' of load case ', currentLoadCase,'/',size(loadCases) - write(incInfo,& - '(a,'//IO_intOut(totalIncsCounter)//& - ',a,'//IO_intOut(sum(loadCases%incs))//& - ',a,'//IO_intOut(stepFraction)//& - ',a,'//IO_intOut(subStepFactor**cutBackLevel)//')') & - 'Increment ',totalIncsCounter,'/',sum(loadCases%incs),& - '-',stepFraction, '/', subStepFactor**cutBackLevel - flush(6) + write(6,'(/,a)') ' ###########################################################################' + write(6,'(1x,a,es12.5'//& + ',a,'//IO_intOut(inc)//',a,'//IO_intOut(loadCases(currentLoadCase)%incs)//& + ',a,'//IO_intOut(stepFraction)//',a,'//IO_intOut(subStepFactor**cutBackLevel)//& + ',a,'//IO_intOut(currentLoadCase)//',a,'//IO_intOut(size(loadCases))//')') & + 'Time', time, & + 's: Increment ', inc, '/', loadCases(currentLoadCase)%incs,& + '-', stepFraction, '/', subStepFactor**cutBackLevel,& + ' of load case ', currentLoadCase,'/',size(loadCases) + write(incInfo,& + '(a,'//IO_intOut(totalIncsCounter)//& + ',a,'//IO_intOut(sum(loadCases%incs))//& + ',a,'//IO_intOut(stepFraction)//& + ',a,'//IO_intOut(subStepFactor**cutBackLevel)//')') & + 'Increment ',totalIncsCounter,'/',sum(loadCases%incs),& + '-',stepFraction, '/', subStepFactor**cutBackLevel + flush(6) !-------------------------------------------------------------------------------------------------- ! forward fields + do field = 1, nActiveFields + select case (loadCases(currentLoadCase)%fieldBC(field)%ID) + case(FIELD_MECH_ID) + call FEM_mech_forward (& + guess,timeinc,timeIncOld,loadCases(currentLoadCase)%fieldBC(field)) + + end select + enddo + +!-------------------------------------------------------------------------------------------------- +! solve fields + stagIter = 0 + stagIterate = .true. + do while (stagIterate) do field = 1, nActiveFields select case (loadCases(currentLoadCase)%fieldBC(field)%ID) case(FIELD_MECH_ID) - call FEM_mech_forward (& - guess,timeinc,timeIncOld,loadCases(currentLoadCase)%fieldBC(field)) + solres(field) = FEM_mech_solution (& + incInfo,timeinc,timeIncOld,loadCases(currentLoadCase)%fieldBC(field)) - end select - enddo - -!-------------------------------------------------------------------------------------------------- -! solve fields - stagIter = 0 - stagIterate = .true. - do while (stagIterate) - do field = 1, nActiveFields - select case (loadCases(currentLoadCase)%fieldBC(field)%ID) - case(FIELD_MECH_ID) - solres(field) = FEM_mech_solution (& - incInfo,timeinc,timeIncOld,loadCases(currentLoadCase)%fieldBC(field)) + end select - end select + if(.not. solres(field)%converged) exit ! no solution found - if(.not. solres(field)%converged) exit ! no solution found - - enddo - stagIter = stagIter + 1 - stagIterate = stagIter < stagItMax & - .and. all(solres(:)%converged) & - .and. .not. all(solres(:)%stagConverged) ! stationary with respect to staggered iteration - enddo - + enddo + stagIter = stagIter + 1 + stagIterate = stagIter < stagItMax & + .and. all(solres(:)%converged) & + .and. .not. all(solres(:)%stagConverged) ! stationary with respect to staggered iteration + enddo + ! check solution - cutBack = .False. - if(.not. all(solres(:)%converged .and. solres(:)%stagConverged)) then ! no solution found - if (cutBackLevel < maxCutBack) then ! do cut back - write(6,'(/,a)') ' cut back detected' - cutBack = .True. - stepFraction = (stepFraction - 1) * subStepFactor ! adjust to new denominator - cutBackLevel = cutBackLevel + 1 - time = time - timeinc ! rewind time - timeinc = timeinc/2.0_pReal - else ! default behavior, exit if spectral solver does not converge - call IO_warning(850) - call quit(-1*(lastRestartWritten+1)) ! quit and provide information about last restart inc written - endif - else - guess = .true. ! start guessing after first converged (sub)inc - timeIncOld = timeinc + cutBack = .False. + if(.not. all(solres(:)%converged .and. solres(:)%stagConverged)) then ! no solution found + if (cutBackLevel < maxCutBack) then ! do cut back + write(6,'(/,a)') ' cut back detected' + cutBack = .True. + stepFraction = (stepFraction - 1) * subStepFactor ! adjust to new denominator + cutBackLevel = cutBackLevel + 1 + time = time - timeinc ! rewind time + timeinc = timeinc/2.0_pReal + else ! default behavior, exit if spectral solver does not converge + call IO_warning(850) + call quit(1) ! quit endif - if (.not. cutBack) then - if (worldrank == 0) write(statUnit,*) totalIncsCounter, time, cutBackLevel, & - solres%converged, solres%iterationsNeeded ! write statistics about accepted solution - endif - enddo subStepLooping - - cutBackLevel = max(0, cutBackLevel - 1) ! try half number of subincs next inc - - if (all(solres(:)%converged)) then - convergedCounter = convergedCounter + 1 - write(6,'(/,a,'//IO_intOut(totalIncsCounter)//',a)') & ! report converged inc - ' increment ', totalIncsCounter, ' converged' else - notConvergedCounter = notConvergedCounter + 1 - write(6,'(/,a,'//IO_intOut(totalIncsCounter)//',a)') & ! report non-converged inc - ' increment ', totalIncsCounter, ' NOT converged' - endif; flush(6) - - if (mod(inc,loadCases(currentLoadCase)%outputFrequency) == 0) then ! at output frequency - write(6,'(1/,a)') ' ... writing results to file ......................................' - call CPFEM_results(totalIncsCounter,time) + guess = .true. ! start guessing after first converged (sub)inc + timeIncOld = timeinc endif - if ( loadCases(currentLoadCase)%restartFrequency > 0 & ! writing of restart info requested ... - .and. mod(inc,loadCases(currentLoadCase)%restartFrequency) == 0) then ! ... and at frequency of writing restart information - restartWrite = .true. ! set restart parameter for FEsolving - lastRestartWritten = inc ! first call to CPFEM_general will write + if (.not. cutBack) then + if (worldrank == 0) write(statUnit,*) totalIncsCounter, time, cutBackLevel, & + solres%converged, solres%iterationsNeeded ! write statistics about accepted solution endif + enddo subStepLooping + + cutBackLevel = max(0, cutBackLevel - 1) ! try half number of subincs next inc + + if (all(solres(:)%converged)) then + write(6,'(/,a,'//IO_intOut(totalIncsCounter)//',a)') & ! report converged inc + ' increment ', totalIncsCounter, ' converged' + else + write(6,'(/,a,'//IO_intOut(totalIncsCounter)//',a)') & ! report non-converged inc + ' increment ', totalIncsCounter, ' NOT converged' + endif; flush(6) + + if (mod(inc,loadCases(currentLoadCase)%outputFrequency) == 0) then ! at output frequency + write(6,'(1/,a)') ' ... writing results to file ......................................' + call CPFEM_results(totalIncsCounter,time) + endif - endif skipping enddo incLooping @@ -413,15 +394,8 @@ program DAMASK_FEM !-------------------------------------------------------------------------------------------------- ! report summary of whole calculation write(6,'(/,a)') ' ###########################################################################' - write(6,'(1x,'//IO_intOut(convergedCounter)//',a,'//IO_intOut(notConvergedCounter + convergedCounter)//',a,f5.1,a)') & - convergedCounter, ' out of ', & - notConvergedCounter + convergedCounter, ' (', & - real(convergedCounter, pReal)/& - real(notConvergedCounter + convergedCounter,pReal)*100.0_pReal, ' %) increments converged!' - flush(6) close(statUnit) - if (notConvergedCounter > 0) call quit(2) ! error if some are not converged call quit(0) ! no complains ;) end program DAMASK_FEM diff --git a/src/mesh/FEM_mech.f90 b/src/mesh/FEM_mech.f90 index eca81ab36..3a19f67c7 100644 --- a/src/mesh/FEM_mech.f90 +++ b/src/mesh/FEM_mech.f90 @@ -62,7 +62,7 @@ module FEM_mech contains !-------------------------------------------------------------------------------------------------- -!> @brief allocates all neccessary fields and fills them with data, potentially from restart info +!> @brief allocates all neccessary fields and fills them with data !-------------------------------------------------------------------------------------------------- subroutine FEM_mech_init(fieldBC) diff --git a/src/mesh/FEM_utilities.f90 b/src/mesh/FEM_utilities.f90 index 70d347b2f..1303f0df8 100644 --- a/src/mesh/FEM_utilities.f90 +++ b/src/mesh/FEM_utilities.f90 @@ -77,7 +77,6 @@ module FEM_utilities real(pReal) :: time = 0.0_pReal !< length of increment integer :: incs = 0, & !< number of increments outputfrequency = 1, & !< frequency of result writes - restartfrequency = 0, & !< frequency of restart writes logscale = 0 !< linear/logarithmic time inc flag logical :: followFormerTrajectory = .true. !< follow trajectory of former loadcase integer, allocatable :: faceID(:) @@ -145,7 +144,6 @@ subroutine utilities_constitutiveResponse(timeinc,P_av,forwardData) call materialpoint_stressAndItsTangent(.true.,timeinc) ! calculate P field - restartWrite = .false. ! reset restartWrite status cutBack = .false. ! reset cutBack status P_av = sum(sum(materialpoint_P,dim=4),dim=3) * wgt ! average of P diff --git a/src/mesh_abaqus.f90 b/src/mesh_abaqus.f90 index 1bbb008d6..15332b3fb 100644 --- a/src/mesh_abaqus.f90 +++ b/src/mesh_abaqus.f90 @@ -454,7 +454,7 @@ subroutine mesh_init(ip,el) myDebug = (iand(debug_level(debug_mesh),debug_levelBasic) /= 0) - call IO_open_inputFile(FILEUNIT,modelName) ! parse info from input file... + call IO_open_inputFile(FILEUNIT) ! parse info from input file... if (myDebug) write(6,'(a)') ' Opened input file'; flush(6) noPart = hasNoPart(FILEUNIT) call mesh_abaqus_count_nodesAndElements(FILEUNIT) diff --git a/src/mesh_grid.f90 b/src/mesh_grid.f90 index bfeb7ce86..2b337f047 100644 --- a/src/mesh_grid.f90 +++ b/src/mesh_grid.f90 @@ -4,7 +4,7 @@ !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief Parse geometry file to set up discretization and geometry for nonlocal model !-------------------------------------------------------------------------------------------------- -module mesh +module mesh_grid #include use PETScsys @@ -14,16 +14,14 @@ module mesh use IO use debug use numerics + use results use discretization use geometry_plastic_nonlocal use FEsolving implicit none private - - real(pReal), dimension(:,:,:), allocatable, public :: & - mesh_ipCoordinates !< IP x,y,z coordinates (after deformation!) - + integer, dimension(3), public, protected :: & grid !< (global) grid integer, public, protected :: & @@ -63,7 +61,7 @@ subroutine mesh_init(ip,el) integer(C_INTPTR_T) :: & devNull, z, z_offset - write(6,'(/,a)') ' <<<+- mesh init -+>>>' + write(6,'(/,a)') ' <<<+- mesh_grid init -+>>>' call readGeom(grid,geomSize,microstructureAt,homogenizationAt) @@ -92,14 +90,24 @@ subroutine mesh_init(ip,el) homogenizationAt = homogenizationAt(product(grid(1:2))*grid3Offset+1: & product(grid(1:2))*(grid3Offset+grid3)) ! reallocate/shrink in case of MPI - mesh_ipCoordinates = IPcoordinates(myGrid,mySize,grid3Offset) call discretization_init(homogenizationAt,microstructureAt, & - reshape(mesh_ipCoordinates,[3,product(myGrid)]), & - Nodes(myGrid,mySize,grid3Offset)) + IPcoordinates0(myGrid,mySize,grid3Offset), & + Nodes0(myGrid,mySize,grid3Offset),& + merge((grid(1)+1) * (grid(2)+1) * (grid3+1),& ! write bottom layer + (grid(1)+1) * (grid(2)+1) * grid3,& ! do not write bottom layer (is top of rank-1) + worldrank<1)) FEsolving_execElem = [1,product(myGrid)] ! parallel loop bounds set to comprise all elements allocate(FEsolving_execIP(2,product(myGrid)),source=1) ! parallel loop bounds set to comprise the only IP +!-------------------------------------------------------------------------------------------------- +! store geometry information for post processing + call results_openJobFile + call results_closeGroup(results_addGroup('geometry')) + call results_addAttribute('grid',grid,'geometry') + call results_addAttribute('size',geomSize,'geometry') + call results_closeJobFile + !-------------------------------------------------------------------------------------------------- ! geometry information required by the nonlocal CP model call geometry_plastic_nonlocal_setIPvolume(reshape([(product(mySize/real(myGrid,pReal)),j=1,product(myGrid))], & @@ -268,15 +276,15 @@ end subroutine readGeom !--------------------------------------------------------------------------------------------------- -!> @brief Calculate position of IPs/cell centres (pretend to be an element) +!> @brief Calculate undeformed position of IPs/cell centres (pretend to be an element) !--------------------------------------------------------------------------------------------------- -function IPcoordinates(grid,geomSize,grid3Offset) +function IPcoordinates0(grid,geomSize,grid3Offset) integer, dimension(3), intent(in) :: grid ! grid (for this process!) real(pReal), dimension(3), intent(in) :: geomSize ! size (for this process!) integer, intent(in) :: grid3Offset ! grid(3) offset - real(pReal), dimension(3,1,product(grid)) :: ipCoordinates + real(pReal), dimension(3,product(grid)) :: ipCoordinates0 integer :: & a,b,c, & @@ -285,22 +293,22 @@ function IPcoordinates(grid,geomSize,grid3Offset) i = 0 do c = 1, grid(3); do b = 1, grid(2); do a = 1, grid(1) i = i + 1 - IPcoordinates(1:3,1,i) = geomSize/real(grid,pReal) * (real([a,b,grid3Offset+c],pReal) -0.5_pReal) + IPcoordinates0(1:3,i) = geomSize/real(grid,pReal) * (real([a,b,grid3Offset+c],pReal) -0.5_pReal) enddo; enddo; enddo -end function IPcoordinates +end function IPcoordinates0 !--------------------------------------------------------------------------------------------------- -!> @brief Calculate position of nodes (pretend to be an element) +!> @brief Calculate position of undeformed nodes (pretend to be an element) !--------------------------------------------------------------------------------------------------- -pure function nodes(grid,geomSize,grid3Offset) +pure function nodes0(grid,geomSize,grid3Offset) integer, dimension(3), intent(in) :: grid ! grid (for this process!) real(pReal), dimension(3), intent(in) :: geomSize ! size (for this process!) integer, intent(in) :: grid3Offset ! grid(3) offset - real(pReal), dimension(3,product(grid+1)) :: nodes + real(pReal), dimension(3,product(grid+1)) :: nodes0 integer :: & a,b,c, & @@ -309,10 +317,10 @@ pure function nodes(grid,geomSize,grid3Offset) n = 0 do c = 0, grid3; do b = 0, grid(2); do a = 0, grid(1) n = n + 1 - nodes(1:3,n) = geomSize/real(grid,pReal) * real([a,b,grid3Offset+c],pReal) + nodes0(1:3,n) = geomSize/real(grid,pReal) * real([a,b,grid3Offset+c],pReal) enddo; enddo; enddo -end function nodes +end function nodes0 !-------------------------------------------------------------------------------------------------- @@ -403,78 +411,4 @@ pure function IPneighborhood(grid) end function IPneighborhood -!!-------------------------------------------------------------------------------------------------- -!!> @brief builds mesh of (distorted) cubes for given coordinates (= center of the cubes) -!!-------------------------------------------------------------------------------------------------- -!function mesh_nodesAroundCentres(gDim,Favg,centres) result(nodes) -! -! real(pReal), intent(in), dimension(:,:,:,:) :: & -! centres -! real(pReal), dimension(3,size(centres,2)+1,size(centres,3)+1,size(centres,4)+1) :: & -! nodes -! real(pReal), intent(in), dimension(3) :: & -! gDim -! real(pReal), intent(in), dimension(3,3) :: & -! Favg -! real(pReal), dimension(3,size(centres,2)+2,size(centres,3)+2,size(centres,4)+2) :: & -! wrappedCentres -! -! integer :: & -! i,j,k,n -! integer, dimension(3), parameter :: & -! diag = 1 -! integer, dimension(3) :: & -! shift = 0, & -! lookup = 0, & -! me = 0, & -! iRes = 0 -! integer, dimension(3,8) :: & -! neighbor = reshape([ & -! 0, 0, 0, & -! 1, 0, 0, & -! 1, 1, 0, & -! 0, 1, 0, & -! 0, 0, 1, & -! 1, 0, 1, & -! 1, 1, 1, & -! 0, 1, 1 ], [3,8]) -! -!!-------------------------------------------------------------------------------------------------- -!! initializing variables -! iRes = [size(centres,2),size(centres,3),size(centres,4)] -! nodes = 0.0_pReal -! wrappedCentres = 0.0_pReal -! -!!-------------------------------------------------------------------------------------------------- -!! building wrappedCentres = centroids + ghosts -! wrappedCentres(1:3,2:iRes(1)+1,2:iRes(2)+1,2:iRes(3)+1) = centres -! do k = 0,iRes(3)+1 -! do j = 0,iRes(2)+1 -! do i = 0,iRes(1)+1 -! if (k==0 .or. k==iRes(3)+1 .or. & ! z skin -! j==0 .or. j==iRes(2)+1 .or. & ! y skin -! i==0 .or. i==iRes(1)+1 ) then ! x skin -! me = [i,j,k] ! me on skin -! shift = sign(abs(iRes+diag-2*me)/(iRes+diag),iRes+diag-2*me) -! lookup = me-diag+shift*iRes -! wrappedCentres(1:3,i+1, j+1, k+1) = & -! centres(1:3,lookup(1)+1,lookup(2)+1,lookup(3)+1) & -! - matmul(Favg, real(shift,pReal)*gDim) -! endif -! enddo; enddo; enddo -! -!!-------------------------------------------------------------------------------------------------- -!! averaging -! do k = 0,iRes(3); do j = 0,iRes(2); do i = 0,iRes(1) -! do n = 1,8 -! nodes(1:3,i+1,j+1,k+1) = & -! nodes(1:3,i+1,j+1,k+1) + wrappedCentres(1:3,i+1+neighbor(1,n), & -! j+1+neighbor(2,n), & -! k+1+neighbor(3,n) ) -! enddo -! enddo; enddo; enddo -! nodes = nodes/8.0_pReal -! -!end function mesh_nodesAroundCentres - -end module mesh +end module mesh_grid diff --git a/src/mesh_marc.f90 b/src/mesh_marc.f90 index 66906207a..f640baa72 100644 --- a/src/mesh_marc.f90 +++ b/src/mesh_marc.f90 @@ -1,7 +1,7 @@ !-------------------------------------------------------------------------------------------------- !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH -!> @author Christoph Koords, Max-Planck-Institut für Eisenforschung GmbH +!> @author Christoph Kords, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief Sets up the mesh for the solver MSC.Marc !-------------------------------------------------------------------------------------------------- @@ -69,7 +69,7 @@ subroutine mesh_init(ip,el) microstructureAt, & homogenizationAt integer:: & - Nnodes !< total number of nodes in mesh + Nnodes !< total number of nodes in mesh real(pReal), dimension(:,:), allocatable :: & ip_reshaped @@ -119,15 +119,17 @@ subroutine mesh_init(ip,el) reshape(connectivity_cell,[elem%NcellNodesPerCell,elem%nIPs*nElems]),& node0_cell,ip_reshaped) +!-------------------------------------------------------------------------------------------------- +! geometry information required by the nonlocal CP model call geometry_plastic_nonlocal_setIPvolume(IPvolume(elem,node0_cell,connectivity_cell)) unscaledNormals = IPareaNormal(elem,nElems,connectivity_cell,node0_cell) call geometry_plastic_nonlocal_setIParea(norm2(unscaledNormals,1)) call geometry_plastic_nonlocal_setIPareaNormal(unscaledNormals/spread(norm2(unscaledNormals,1),1,3)) call geometry_plastic_nonlocal_results - end subroutine mesh_init + !-------------------------------------------------------------------------------------------------- !> @brief Writes all information needed for the DADF5 geometry !-------------------------------------------------------------------------------------------------- @@ -201,9 +203,9 @@ subroutine inputRead(elem,node0_elem,connectivity_elem,microstructureAt,homogeni character(len=64), dimension(:), allocatable :: & nameElemSet integer, dimension(:,:), allocatable :: & - mapElemSet !< list of elements in elementSet + mapElemSet !< list of elements in elementSet - inputFile = IO_read_ASCII(trim(modelName)//trim(InputFileExtension)) + inputFile = IO_read_ASCII(trim(getSolverJobName())//trim(InputFileExtension)) call inputRead_fileFormat(fileFormatVersion, & inputFile) call inputRead_tableStyles(initialcondTableStyle,hypoelasticTableStyle, & @@ -214,7 +216,7 @@ subroutine inputRead(elem,node0_elem,connectivity_elem,microstructureAt,homogeni call inputRead_NnodesAndElements(nNodes,nElems,& inputFile) - call IO_open_inputFile(FILEUNIT,modelName) ! ToDo: It would be better to use fileContent + call IO_open_inputFile(FILEUNIT) ! ToDo: It would be better to use fileContent call inputRead_mapElemSets(nameElemSet,mapElemSet,& FILEUNIT) diff --git a/src/numerics.f90 b/src/numerics.f90 index 0f63f87ab..6776ec178 100644 --- a/src/numerics.f90 +++ b/src/numerics.f90 @@ -82,9 +82,6 @@ module numerics &-damage_snes_type ngmres & &-thermal_snes_type ngmres ', & petsc_options = '' - logical, protected, public :: & - continueCalculation = .false. !< false:exit if BVP solver does not converge, true: continue calculation despite BVP solver not converging - #endif !-------------------------------------------------------------------------------------------------- @@ -259,8 +256,6 @@ subroutine numerics_init err_stress_tolrel = IO_floatValue(line,chunkPos,2) case ('err_stress_tolabs') err_stress_tolabs = IO_floatValue(line,chunkPos,2) - case ('continuecalculation') - continueCalculation = IO_intValue(line,chunkPos,2) > 0 case ('petsc_options') petsc_options = trim(line(chunkPos(4):)) case ('err_curl_tolabs') @@ -354,7 +349,6 @@ subroutine numerics_init !-------------------------------------------------------------------------------------------------- ! spectral parameters #ifdef Grid - write(6,'(a24,1x,L8)') ' continueCalculation: ',continueCalculation write(6,'(a24,1x,es8.1)') ' err_stress_tolAbs: ',err_stress_tolAbs write(6,'(a24,1x,es8.1)') ' err_stress_tolRel: ',err_stress_tolRel write(6,'(a24,1x,es8.1)') ' err_div_tolAbs: ',err_div_tolAbs diff --git a/src/plastic_disloUCLA.f90 b/src/plastic_disloUCLA.f90 index 83c96e1ff..29ef0fcc9 100644 --- a/src/plastic_disloUCLA.f90 +++ b/src/plastic_disloUCLA.f90 @@ -18,11 +18,6 @@ module plastic_disloUCLA implicit none private - - integer, dimension(:,:), allocatable, target, public :: & - plastic_disloUCLA_sizePostResult !< size of each post result output - character(len=64), dimension(:,:), allocatable, target, public :: & - plastic_disloUCLA_output !< name of each post result output real(pReal), parameter, private :: & kB = 1.38e-23_pReal !< Boltzmann constant in J/Kelvin @@ -35,7 +30,7 @@ module plastic_disloUCLA dot_gamma_sl_ID, & gamma_sl_ID, & Lambda_sl_ID, & - thresholdstress_ID + tau_pass_ID end enum type, private :: tParameters @@ -106,7 +101,6 @@ module plastic_disloUCLA plastic_disloUCLA_dependentState, & plastic_disloUCLA_LpAndItsTangent, & plastic_disloUCLA_dotState, & - plastic_disloUCLA_postResults, & plastic_disloUCLA_results private :: & kinetics @@ -148,10 +142,6 @@ subroutine plastic_disloUCLA_init() if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance - allocate(plastic_disloUCLA_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(plastic_disloUCLA_output(maxval(phase_Noutput),Ninstance)) - plastic_disloUCLA_output = '' - allocate(param(Ninstance)) allocate(state(Ninstance)) allocate(dotState(Ninstance)) @@ -284,13 +274,11 @@ subroutine plastic_disloUCLA_init() case ('mfp','mfp_slip') outputID = merge(Lambda_sl_ID,undefined_ID,prm%sum_N_sl>0) case ('threshold_stress','threshold_stress_slip') - outputID = merge(thresholdstress_ID,undefined_ID,prm%sum_N_sl>0) + outputID = merge(tau_pass_ID,undefined_ID,prm%sum_N_sl>0) end select if (outputID /= undefined_ID) then - plastic_disloUCLA_output(i,phase_plasticityInstance(p)) = outputs(i) - plastic_disloUCLA_sizePostResult(i,phase_plasticityInstance(p)) = prm%sum_N_sl prm%outputID = [prm%outputID, outputID] endif @@ -304,7 +292,6 @@ subroutine plastic_disloUCLA_init() call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0, & prm%sum_N_sl,0,0) - plasticState(p)%sizePostResults = sum(plastic_disloUCLA_sizePostResult(:,phase_plasticityInstance(p))) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -472,59 +459,6 @@ subroutine plastic_disloUCLA_dependentState(instance,of) end subroutine plastic_disloUCLA_dependentState -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function plastic_disloUCLA_postResults(Mp,T,instance,of) result(postResults) - - real(pReal), dimension(3,3), intent(in) :: & - Mp !< Mandel stress - real(pReal), intent(in) :: & - T !< temperature - integer, intent(in) :: & - instance, & - of - - real(pReal), dimension(sum(plastic_disloUCLA_sizePostResult(:,instance))) :: & - postResults - - integer :: & - o,c - real(pReal), dimension(param(instance)%sum_N_sl) :: & - gdot_pos,gdot_neg - - c = 0 - - associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) - - outputsLoop: do o = 1,size(prm%outputID) - select case(prm%outputID(o)) - - case (rho_mob_ID) - postResults(c+1:c+prm%sum_N_sl) = stt%rho_mob(1:prm%sum_N_sl,of) - case (rho_dip_ID) - postResults(c+1:c+prm%sum_N_sl) = stt%rho_dip(1:prm%sum_N_sl,of) - case (dot_gamma_sl_ID) - call kinetics(Mp,T,instance,of,gdot_pos,gdot_neg) - postResults(c+1:c+prm%sum_N_sl) = gdot_pos + gdot_neg - case (gamma_sl_ID) - postResults(c+1:c+prm%sum_N_sl) = stt%gamma_sl(1:prm%sum_N_sl, of) - case (Lambda_sl_ID) - postResults(c+1:c+prm%sum_N_sl) = dst%Lambda_sl(1:prm%sum_N_sl, of) - case (thresholdstress_ID) - postResults(c+1:c+prm%sum_N_sl) = dst%threshold_stress(1:prm%sum_N_sl,of) - - end select - - c = c + prm%sum_N_sl - - enddo outputsLoop - - end associate - -end function plastic_disloUCLA_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- @@ -546,12 +480,12 @@ subroutine plastic_disloUCLA_results(instance,group) call results_writeDataset(group,stt%rho_dip,'rho_dip',& 'dislocation dipole density''1/m²') case (dot_gamma_sl_ID) - call results_writeDataset(group,stt%gamma_sl,'dot_gamma_sl',& + call results_writeDataset(group,stt%gamma_sl,'dot_gamma_sl',& ! this is not dot!! 'plastic shear','1') case (Lambda_sl_ID) call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',& 'mean free path for slip','m') - case (thresholdstress_ID) + case (tau_pass_ID) call results_writeDataset(group,dst%threshold_stress,'tau_pass',& 'threshold stress for slip','Pa') end select diff --git a/src/plastic_dislotwin.f90 b/src/plastic_dislotwin.f90 index 4e085478f..1f731a891 100644 --- a/src/plastic_dislotwin.f90 +++ b/src/plastic_dislotwin.f90 @@ -20,11 +20,6 @@ module plastic_dislotwin implicit none private - - integer, dimension(:,:), allocatable, target, public :: & - plastic_dislotwin_sizePostResult !< size of each post result output - character(len=64), dimension(:,:), allocatable, target, public :: & - plastic_dislotwin_output !< name of each post result output real(pReal), parameter :: & kB = 1.38e-23_pReal !< Boltzmann constant in J/Kelvin @@ -38,7 +33,7 @@ module plastic_dislotwin gamma_sl_ID, & Lambda_sl_ID, & resolved_stress_slip_ID, & - threshold_stress_slip_ID, & + tau_pass_ID, & edge_dipole_distance_ID, & f_tw_ID, & Lambda_tw_ID, & @@ -167,7 +162,6 @@ module plastic_dislotwin plastic_dislotwin_dependentState, & plastic_dislotwin_LpAndItsTangent, & plastic_dislotwin_dotState, & - plastic_dislotwin_postResults, & plastic_dislotwin_results contains @@ -213,10 +207,6 @@ subroutine plastic_dislotwin_init if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance - - allocate(plastic_dislotwin_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(plastic_dislotwin_output(maxval(phase_Noutput),Ninstance)) - plastic_dislotwin_output = '' allocate(param(Ninstance)) allocate(state(Ninstance)) @@ -487,7 +477,7 @@ subroutine plastic_dislotwin_init outputID = merge(Lambda_sl_ID,undefined_ID,prm%sum_N_sl > 0) outputSize = prm%sum_N_sl case ('tau_pass') - outputID= merge(threshold_stress_slip_ID,undefined_ID,prm%sum_N_sl > 0) + outputID= merge(tau_pass_ID,undefined_ID,prm%sum_N_sl > 0) outputSize = prm%sum_N_sl case ('f_tw') @@ -507,8 +497,6 @@ subroutine plastic_dislotwin_init end select if (outputID /= undefined_ID) then - plastic_dislotwin_output(i,phase_plasticityInstance(p)) = outputs(i) - plastic_dislotwin_sizePostResult(i,phase_plasticityInstance(p)) = outputSize prm%outputID = [prm%outputID, outputID] endif @@ -524,8 +512,6 @@ subroutine plastic_dislotwin_init call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0, & prm%sum_N_sl,prm%sum_N_tw,prm%sum_N_tr) - plasticState(p)%sizePostResults = sum(plastic_dislotwin_sizePostResult(:,phase_plasticityInstance(p))) - !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -936,82 +922,6 @@ subroutine plastic_dislotwin_dependentState(T,instance,of) end subroutine plastic_dislotwin_dependentState -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function plastic_dislotwin_postResults(Mp,T,instance,of) result(postResults) - - real(pReal), dimension(3,3),intent(in) :: & - Mp !< 2nd Piola Kirchhoff stress tensor in Mandel notation - real(pReal), intent(in) :: & - T !< temperature at integration point - integer, intent(in) :: & - instance, & - of - - real(pReal), dimension(sum(plastic_dislotwin_sizePostResult(:,instance))) :: & - postResults - - integer :: & - o,c,j - - associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) - - c = 0 - - do o = 1,size(prm%outputID) - select case(prm%outputID(o)) - - case (rho_mob_ID) - postResults(c+1:c+prm%sum_N_sl) = stt%rho_mob(1:prm%sum_N_sl,of) - c = c + prm%sum_N_sl - case (rho_dip_ID) - postResults(c+1:c+prm%sum_N_sl) = stt%rho_dip(1:prm%sum_N_sl,of) - c = c + prm%sum_N_sl - case (dot_gamma_sl_ID) - call kinetics_slip(Mp,T,instance,of,postResults(c+1:c+prm%sum_N_sl)) - c = c + prm%sum_N_sl - case (gamma_sl_ID) - postResults(c+1:c+prm%sum_N_sl) = stt%gamma_sl(1:prm%sum_N_sl,of) - c = c + prm%sum_N_sl - case (Lambda_sl_ID) - postResults(c+1:c+prm%sum_N_sl) = dst%Lambda_sl(1:prm%sum_N_sl,of) - c = c + prm%sum_N_sl - case (resolved_stress_slip_ID) - do j = 1, prm%sum_N_sl - postResults(c+j) = math_mul33xx33(Mp,prm%P_sl(1:3,1:3,j)) - enddo - c = c + prm%sum_N_sl - case (threshold_stress_slip_ID) - postResults(c+1:c+prm%sum_N_sl) = dst%tau_pass(1:prm%sum_N_sl,of) - c = c + prm%sum_N_sl - - case (f_tw_ID) - postResults(c+1:c+prm%sum_N_tw) = stt%f_tw(1:prm%sum_N_tw,of) - c = c + prm%sum_N_tw - case (Lambda_tw_ID) - postResults(c+1:c+prm%sum_N_tw) = dst%Lambda_tw(1:prm%sum_N_tw,of) - c = c + prm%sum_N_tw - case (resolved_stress_twin_ID) - do j = 1, prm%sum_N_tw - postResults(c+j) = math_mul33xx33(Mp,prm%P_tw(1:3,1:3,j)) - enddo - c = c + prm%sum_N_tw - case (tau_hat_tw_ID) - postResults(c+1:c+prm%sum_N_tw) = dst%tau_hat_tw(1:prm%sum_N_tw,of) - c = c + prm%sum_N_tw - - case (f_tr_ID) - postResults(c+1:c+prm%sum_N_tr) = stt%f_tr(1:prm%sum_N_tr,of) - c = c + prm%sum_N_tr - end select - enddo - - end associate - -end function plastic_dislotwin_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- @@ -1038,7 +948,7 @@ subroutine plastic_dislotwin_results(instance,group) case (Lambda_sl_ID) call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',& 'mean free path for slip','m') - case (threshold_stress_slip_ID) + case (tau_pass_ID) call results_writeDataset(group,dst%tau_pass,'tau_pass',& 'passing stress for slip','Pa') diff --git a/src/plastic_isotropic.f90 b/src/plastic_isotropic.f90 index 18b6f8e86..9beb2262b 100644 --- a/src/plastic_isotropic.f90 +++ b/src/plastic_isotropic.f90 @@ -20,11 +20,6 @@ module plastic_isotropic implicit none private - integer, dimension(:,:), allocatable, target, public :: & - plastic_isotropic_sizePostResult !< size of each post result output - character(len=64), dimension(:,:), allocatable, target, public :: & - plastic_isotropic_output !< name of each post result output - enum, bind(c) enumerator :: & undefined_ID, & @@ -74,7 +69,6 @@ module plastic_isotropic plastic_isotropic_LpAndItsTangent, & plastic_isotropic_LiAndItsTangent, & plastic_isotropic_dotState, & - plastic_isotropic_postResults, & plastic_isotropic_results contains @@ -110,10 +104,6 @@ subroutine plastic_isotropic_init if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance - allocate(plastic_isotropic_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(plastic_isotropic_output(maxval(phase_Noutput),Ninstance)) - plastic_isotropic_output = '' - allocate(param(Ninstance)) allocate(state(Ninstance)) allocate(dotState(Ninstance)) @@ -151,7 +141,7 @@ subroutine plastic_isotropic_init ! sanity checks extmsg = '' if (prm%aTol_gamma <= 0.0_pReal) extmsg = trim(extmsg)//' aTol_gamma' - if (prm%xi_0 < 0.0_pReal) extmsg = trim(extmsg)//' xi_0' + if (prm%xi_0 < 0.0_pReal) extmsg = trim(extmsg)//' xi_0' if (prm%dot_gamma_0 <= 0.0_pReal) extmsg = trim(extmsg)//' dot_gamma_0' if (prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' n' if (prm%a <= 0.0_pReal) extmsg = trim(extmsg)//' a' @@ -180,8 +170,6 @@ subroutine plastic_isotropic_init end select if (outputID /= undefined_ID) then - plastic_isotropic_output(i,phase_plasticityInstance(p)) = outputs(i) - plastic_isotropic_sizePostResult(i,phase_plasticityInstance(p)) = 1 prm%outputID = [prm%outputID, outputID] endif @@ -195,7 +183,6 @@ subroutine plastic_isotropic_init call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0, & 1,0,0) - plasticState(p)%sizePostResults = sum(plastic_isotropic_sizePostResult(:,phase_plasticityInstance(p))) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -382,54 +369,6 @@ subroutine plastic_isotropic_dotState(Mp,instance,of) end subroutine plastic_isotropic_dotState -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function plastic_isotropic_postResults(Mp,instance,of) result(postResults) - - real(pReal), dimension(3,3), intent(in) :: & - Mp !< Mandel stress - integer, intent(in) :: & - instance, & - of - - real(pReal), dimension(sum(plastic_isotropic_sizePostResult(:,instance))) :: & - postResults - - real(pReal) :: & - norm_Mp !< norm of the Mandel stress - integer :: & - o,c - - associate(prm => param(instance), stt => state(instance)) - - if (prm%dilatation) then - norm_Mp = sqrt(math_mul33xx33(Mp,Mp)) - else - norm_Mp = sqrt(math_mul33xx33(math_deviatoric33(Mp),math_deviatoric33(Mp))) - endif - - c = 0 - - outputsLoop: do o = 1,size(prm%outputID) - select case(prm%outputID(o)) - - case (xi_ID) - postResults(c+1) = stt%xi(of) - c = c + 1 - case (dot_gamma_ID) - postResults(c+1) = prm%dot_gamma_0 & - * (sqrt(1.5_pReal) * norm_Mp /(prm%M * stt%xi(of)))**prm%n - c = c + 1 - - end select - enddo outputsLoop - - end associate - -end function plastic_isotropic_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- diff --git a/src/plastic_kinematichardening.f90 b/src/plastic_kinematichardening.f90 index f2183327c..2a3dc4640 100644 --- a/src/plastic_kinematichardening.f90 +++ b/src/plastic_kinematichardening.f90 @@ -19,11 +19,6 @@ module plastic_kinehardening implicit none private - integer, dimension(:,:), allocatable, target, public :: & - plastic_kinehardening_sizePostResult !< size of each post result output - character(len=64), dimension(:,:), allocatable, target, public :: & - plastic_kinehardening_output !< name of each post result output - enum, bind(c) enumerator :: & undefined_ID, & @@ -90,7 +85,6 @@ module plastic_kinehardening plastic_kinehardening_LpAndItsTangent, & plastic_kinehardening_dotState, & plastic_kinehardening_deltaState, & - plastic_kinehardening_postResults, & plastic_kinehardening_results contains @@ -127,10 +121,6 @@ subroutine plastic_kinehardening_init if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance - allocate(plastic_kinehardening_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(plastic_kinehardening_output(maxval(phase_Noutput),Ninstance)) - plastic_kinehardening_output = '' - allocate(param(Ninstance)) allocate(state(Ninstance)) allocate(dotState(Ninstance)) @@ -247,8 +237,6 @@ subroutine plastic_kinehardening_init end select if (outputID /= undefined_ID) then - plastic_kinehardening_output(i,phase_plasticityInstance(p)) = outputs(i) - plastic_kinehardening_sizePostResult(i,phase_plasticityInstance(p)) = prm%totalNslip prm%outputID = [prm%outputID , outputID] endif @@ -263,7 +251,6 @@ subroutine plastic_kinehardening_init call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,sizeDeltaState, & prm%totalNslip,0,0) - plasticState(p)%sizePostResults = sum(plastic_kinehardening_sizePostResult(:,phase_plasticityInstance(p))) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -446,63 +433,6 @@ subroutine plastic_kinehardening_deltaState(Mp,instance,of) end subroutine plastic_kinehardening_deltaState -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function plastic_kinehardening_postResults(Mp,instance,of) result(postResults) - - real(pReal), dimension(3,3), intent(in) :: & - Mp !< Mandel stress - integer, intent(in) :: & - instance, & - of - - real(pReal), dimension(sum(plastic_kinehardening_sizePostResult(:,instance))) :: & - postResults - - integer :: & - o,c,i - real(pReal), dimension(param(instance)%totalNslip) :: & - gdot_pos,gdot_neg - - c = 0 - - associate(prm => param(instance), stt => state(instance)) - - outputsLoop: do o = 1,size(prm%outputID) - select case(prm%outputID(o)) - - case (crss_ID) - postResults(c+1:c+prm%totalNslip) = stt%crss(:,of) - case(crss_back_ID) - postResults(c+1:c+prm%totalNslip) = stt%crss_back(:,of) - case (sense_ID) - postResults(c+1:c+prm%totalNslip) = stt%sense(:,of) - case (chi0_ID) - postResults(c+1:c+prm%totalNslip) = stt%chi0(:,of) - case (gamma0_ID) - postResults(c+1:c+prm%totalNslip) = stt%gamma0(:,of) - case (accshear_ID) - postResults(c+1:c+prm%totalNslip) = stt%accshear(:,of) - case (shearrate_ID) - call kinetics(Mp,instance,of,gdot_pos,gdot_neg) - postResults(c+1:c+prm%totalNslip) = gdot_pos+gdot_neg - case (resolvedstress_ID) - do i = 1, prm%totalNslip - postResults(c+i) = math_mul33xx33(Mp,prm%Schmid(1:3,1:3,i)) - enddo - - end select - - c = c + prm%totalNslip - - enddo outputsLoop - - end associate - -end function plastic_kinehardening_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- diff --git a/src/plastic_none.f90 b/src/plastic_none.f90 index fa913df4c..a4979bb2c 100644 --- a/src/plastic_none.f90 +++ b/src/plastic_none.f90 @@ -40,8 +40,6 @@ subroutine plastic_none_init NipcMyPhase = count(material_phaseAt == p) * discretization_nIP call material_allocatePlasticState(p,NipcMyPhase,0,0,0, & 0,0,0) - plasticState(p)%sizePostResults = 0 - enddo end subroutine plastic_none_init diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 838143620..5375aba49 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -9,7 +9,6 @@ module plastic_nonlocal use IO use math use debug - use mesh use material use lattice use rotations @@ -25,15 +24,11 @@ module plastic_nonlocal implicit none private - real(pReal), parameter, private :: & + real(pReal), parameter :: & KB = 1.38e-23_pReal !< Physical parameter, Boltzmann constant in J/Kelvin - - integer, dimension(:,:), allocatable, target, public :: & - plastic_nonlocal_sizePostResult !< size of each post result output - character(len=64), dimension(:,:), allocatable, target, public :: & + character(len=64), dimension(:,:), allocatable :: & plastic_nonlocal_output !< name of each post result output - ! storage order of dislocation types integer, dimension(8), parameter :: & @@ -55,18 +50,18 @@ module plastic_nonlocal mob_scr_neg = 4 !< mobile screw positive ! BEGIN DEPRECATES - integer, dimension(:,:,:), allocatable, private :: & + integer, dimension(:,:,:), allocatable :: & iRhoU, & !< state indices for unblocked density iRhoB, & !< state indices for blocked density iRhoD, & !< state indices for dipole density iV, & !< state indices for dislcation velocities iD !< state indices for stable dipole height - integer, dimension(:), allocatable, private, protected :: & + integer, dimension(:), allocatable :: & totalNslip !< total number of active slip systems for each instance !END DEPRECATED - real(pReal), dimension(:,:,:,:,:,:), allocatable, private :: & - compatibility !< slip system compatibility between me and my neighbors + real(pReal), dimension(:,:,:,:,:,:), allocatable :: & + compatibility !< slip system compatibility between me and my neighbors enum, bind(c) enumerator :: & @@ -82,31 +77,19 @@ module plastic_nonlocal rho_dip_edg_ID, & rho_dip_scr_ID, & rho_forest_ID, & - shearrate_ID, & resolvedstress_back_ID, & - resistance_ID, & + tau_pass_ID, & rho_dot_sgl_ID, & rho_dot_sgl_mobile_ID, & rho_dot_dip_ID, & - rho_dot_gen_edge_ID, & - rho_dot_gen_screw_ID, & - rho_dot_sgl2dip_edge_ID, & - rho_dot_sgl2dip_screw_ID, & - rho_dot_ann_ath_ID, & - rho_dot_ann_the_edge_ID, & - rho_dot_ann_the_screw_ID, & - rho_dot_edgejogs_ID, & - rho_dot_flux_mobile_ID, & - rho_dot_flux_edge_ID, & - rho_dot_flux_screw_ID, & - velocity_edge_pos_ID, & - velocity_edge_neg_ID, & - velocity_screw_pos_ID, & - velocity_screw_neg_ID, & - accumulatedshear_ID + v_edg_pos_ID, & + v_edg_neg_ID, & + v_scr_pos_ID, & + v_scr_neg_ID, & + gamma_ID end enum - type, private :: tParameters !< container type for internal constitutive parameters + type :: tParameters !< container type for internal constitutive parameters real(pReal) :: & atomicVolume, & !< atomic volume Dsd0, & !< prefactor for self-diffusion coefficient @@ -156,19 +139,19 @@ module plastic_nonlocal interactionSlipSlip ,& !< coefficients for slip-slip interaction forestProjection_Edge, & !< matrix of forest projections of edge dislocations forestProjection_Screw !< matrix of forest projections of screw dislocations - real(pReal), dimension(:), allocatable, private :: & + real(pReal), dimension(:), allocatable :: & nonSchmidCoeff - real(pReal), dimension(:,:,:), allocatable, private :: & + real(pReal), dimension(:,:,:), allocatable :: & Schmid, & !< Schmid contribution nonSchmid_pos, & nonSchmid_neg !< combined projection of Schmid and non-Schmid contributions to the resolved shear stress (only for screws) integer :: & totalNslip - integer, dimension(:) ,allocatable , public:: & + integer, dimension(:) ,allocatable :: & Nslip,& colinearSystem !< colinear system to the active slip system (only valid for fcc!) - logical, private :: & + logical :: & shortRangeStressCorrection, & !< flag indicating the use of the short range stress correction by a excess density gradient term probabilisticMultiplication @@ -177,25 +160,13 @@ module plastic_nonlocal end type tParameters - type, private :: tNonlocalMicrostructure + type :: tNonlocalMicrostructure real(pReal), allocatable, dimension(:,:) :: & - tau_Threshold, & + tau_pass, & tau_Back end type tNonlocalMicrostructure - type, private :: tOutput !< container type for storage of output results - real(pReal), dimension(:,:), allocatable, private :: & - rhoDotEdgeJogs - real(pReal), dimension(:,:,:), allocatable, private :: & - rhoDotFlux, & - rhoDotMultiplication, & - rhoDotSingle2DipoleGlide, & - rhoDotAthermalAnnihilation, & - rhoDotThermalAnnihilation - end type tOutput - - - type, private :: tNonlocalState + type :: tNonlocalState real(pReal), pointer, dimension(:,:) :: & rho, & ! < all dislocations rhoSgl, & @@ -213,21 +184,24 @@ module plastic_nonlocal rho_dip_edg, & rho_dip_scr, & rho_forest, & - accumulatedshear, & - v + gamma, & + v, & + v_edg_pos, & + v_edg_neg, & + v_scr_pos, & + v_scr_neg end type tNonlocalState - type(tNonlocalState), allocatable, dimension(:), private :: & + type(tNonlocalState), allocatable, dimension(:) :: & deltaState, & dotState, & state - type(tParameters), dimension(:), allocatable, private :: param !< containers of constitutive parameters (len Ninstance) + type(tParameters), dimension(:), allocatable :: param !< containers of constitutive parameters (len Ninstance) - type(tOutput), dimension(:), allocatable, private :: results - type(tNonlocalMicrostructure), dimension(:), allocatable, private :: microstructure + type(tNonlocalMicrostructure), dimension(:), allocatable :: microstructure - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & + integer(kind(undefined_ID)), dimension(:,:), allocatable :: & plastic_nonlocal_outputID !< ID of each post result output public :: & @@ -237,7 +211,6 @@ module plastic_nonlocal plastic_nonlocal_dotState, & plastic_nonlocal_deltaState, & plastic_nonlocal_updateCompatibility, & - plastic_nonlocal_postResults, & plastic_nonlocal_results private :: & @@ -290,9 +263,7 @@ subroutine plastic_nonlocal_init allocate(dotState(maxNinstances)) allocate(deltaState(maxNinstances)) allocate(microstructure(maxNinstances)) - allocate(results(maxNinstances)) - allocate(plastic_nonlocal_sizePostResult(maxval(phase_Noutput), maxNinstances), source=0) allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) plastic_nonlocal_output = '' allocate(plastic_nonlocal_outputID(maxval(phase_Noutput), maxNinstances), source=undefined_ID) @@ -306,7 +277,6 @@ subroutine plastic_nonlocal_init dot => dotState(phase_plasticityInstance(p)), & stt => state(phase_plasticityInstance(p)), & del => deltaState(phase_plasticityInstance(p)), & - res => results(phase_plasticityInstance(p)), & dst => microstructure(phase_plasticityInstance(p)), & config => config_phase(p)) @@ -477,77 +447,52 @@ subroutine plastic_nonlocal_init do i=1, size(outputs) outputID = undefined_ID select case(trim(outputs(i))) - case ('rho_sgl_edge_pos_mobile') + case ('rho_sgl_mob_edg_pos') outputID = merge(rho_sgl_mob_edg_pos_ID,undefined_ID,prm%totalNslip>0) - case ('rho_sgl_edge_neg_mobile') + case ('rho_sgl_mob_edg_neg') outputID = merge(rho_sgl_mob_edg_neg_ID,undefined_ID,prm%totalNslip>0) - case ('rho_sgl_screw_pos_mobile') + case ('rho_sgl_mob_scr_pos') outputID = merge(rho_sgl_mob_scr_pos_ID,undefined_ID,prm%totalNslip>0) - case ('rho_sgl_screw_neg_mobile') + case ('rho_sgl_mob_scr_neg') outputID = merge(rho_sgl_mob_scr_neg_ID,undefined_ID,prm%totalNslip>0) - case ('rho_sgl_edge_pos_immobile') + case ('rho_sgl_imm_edg_pos') outputID = merge(rho_sgl_imm_edg_pos_ID,undefined_ID,prm%totalNslip>0) - case ('rho_sgl_edge_neg_immobile') + case ('rho_sgl_imm_edg_neg') outputID = merge(rho_sgl_imm_edg_neg_ID,undefined_ID,prm%totalNslip>0) - case ('rho_sgl_screw_pos_immobile') + case ('rho_sgl_imm_scr_pos') outputID = merge(rho_sgl_imm_scr_pos_ID,undefined_ID,prm%totalNslip>0) - case ('rho_sgl_screw_neg_immobile') + case ('rho_sgl_imm_scr_neg') outputID = merge(rho_sgl_imm_scr_neg_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dip_edge') + case ('rho_dip_edg') outputID = merge(rho_dip_edg_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dip_screw') + case ('rho_dip_scr') outputID = merge(rho_dip_scr_ID,undefined_ID,prm%totalNslip>0) case ('rho_forest') outputID = merge(rho_forest_ID,undefined_ID,prm%totalNslip>0) - case ('shearrate') - outputID = merge(shearrate_ID,undefined_ID,prm%totalNslip>0) case ('resolvedstress_back') outputID = merge(resolvedstress_back_ID,undefined_ID,prm%totalNslip>0) - case ('resistance') - outputID = merge(resistance_ID,undefined_ID,prm%totalNslip>0) + case ('tau_pass') + outputID = merge(tau_pass_ID,undefined_ID,prm%totalNslip>0) case ('rho_dot_sgl') outputID = merge(rho_dot_sgl_ID,undefined_ID,prm%totalNslip>0) case ('rho_dot_sgl_mobile') outputID = merge(rho_dot_sgl_mobile_ID,undefined_ID,prm%totalNslip>0) case ('rho_dot_dip') outputID = merge(rho_dot_dip_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_gen_edge') - outputID = merge(rho_dot_gen_edge_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_gen_screw') - outputID = merge(rho_dot_gen_screw_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_sgl2dip_edge') - outputID = merge(rho_dot_sgl2dip_edge_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_sgl2dip_screw') - outputID = merge(rho_dot_sgl2dip_screw_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_ann_ath') - outputID = merge(rho_dot_ann_ath_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_ann_the_edge') - outputID = merge(rho_dot_ann_the_edge_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_ann_the_screw') - outputID = merge(rho_dot_ann_the_screw_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_edgejogs') - outputID = merge(rho_dot_edgejogs_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_flux_mobile') - outputID = merge(rho_dot_flux_mobile_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_flux_edge') - outputID = merge(rho_dot_flux_edge_ID,undefined_ID,prm%totalNslip>0) - case ('rho_dot_flux_screw') - outputID = merge(rho_dot_flux_screw_ID,undefined_ID,prm%totalNslip>0) - case ('velocity_edge_pos') - outputID = merge(velocity_edge_pos_ID,undefined_ID,prm%totalNslip>0) - case ('velocity_edge_neg') - outputID = merge(velocity_edge_neg_ID,undefined_ID,prm%totalNslip>0) - case ('velocity_screw_pos') - outputID = merge(velocity_screw_pos_ID,undefined_ID,prm%totalNslip>0) - case ('velocity_screw_neg') - outputID = merge(velocity_screw_neg_ID,undefined_ID,prm%totalNslip>0) - case ('accumulatedshear','accumulated_shear') - outputID = merge(accumulatedshear_ID,undefined_ID,prm%totalNslip>0) + case ('v_edg_pos') + outputID = merge(v_edg_pos_ID,undefined_ID,prm%totalNslip>0) + case ('v_edg_neg') + outputID = merge(v_edg_neg_ID,undefined_ID,prm%totalNslip>0) + case ('v_scr_pos') + outputID = merge(v_scr_pos_ID,undefined_ID,prm%totalNslip>0) + case ('v_scr_neg') + outputID = merge(v_scr_neg_ID,undefined_ID,prm%totalNslip>0) + case ('gamma') + outputID = merge(gamma_ID,undefined_ID,prm%totalNslip>0) end select if (outputID /= undefined_ID) then plastic_nonlocal_output(i,phase_plasticityInstance(p)) = outputs(i) - plastic_nonlocal_sizePostResult(i,phase_plasticityInstance(p)) = prm%totalNslip prm%outputID = [prm%outputID , outputID] endif @@ -561,7 +506,7 @@ subroutine plastic_nonlocal_init 'rhoSglEdgePosImmobile ','rhoSglEdgeNegImmobile ', & 'rhoSglScrewPosImmobile','rhoSglScrewNegImmobile', & 'rhoDipEdge ','rhoDipScrew ', & - 'accumulatedshear ' ]) * prm%totalNslip !< "basic" microstructural state variables that are independent from other state variables + 'gamma ' ]) * prm%totalNslip !< "basic" microstructural state variables that are independent from other state variables sizeDependentState = size([ 'rhoForest ']) * prm%totalNslip !< microstructural state variables that depend on other state variables sizeState = sizeDotState + sizeDependentState & + size([ 'velocityEdgePos ','velocityEdgeNeg ', & @@ -573,7 +518,6 @@ subroutine plastic_nonlocal_init prm%totalNslip,0,0) plasticState(p)%nonlocal = .true. plasticState(p)%offsetDeltaState = 0 ! ToDo: state structure does not follow convention - plasticState(p)%sizePostResults = sum(plastic_nonlocal_sizePostResult(:,phase_plasticityInstance(p))) totalNslip(phase_plasticityInstance(p)) = prm%totalNslip @@ -598,67 +542,63 @@ subroutine plastic_nonlocal_init dot%rho_sgl_mob_edg_neg => plasticState(p)%dotState (1*prm%totalNslip+1: 2*prm%totalNslip,:) del%rho_sgl_mob_edg_neg => plasticState(p)%deltaState (1*prm%totalNslip+1: 2*prm%totalNslip,:) - stt%rho_sgl_mob_scr_pos => plasticState(p)%state (2*prm%totalNslip+1: 3*prm%totalNslip,:) - dot%rho_sgl_mob_scr_pos => plasticState(p)%dotState (2*prm%totalNslip+1: 3*prm%totalNslip,:) - del%rho_sgl_mob_scr_pos => plasticState(p)%deltaState (2*prm%totalNslip+1: 3*prm%totalNslip,:) + stt%rho_sgl_mob_scr_pos => plasticState(p)%state (2*prm%totalNslip+1: 3*prm%totalNslip,:) + dot%rho_sgl_mob_scr_pos => plasticState(p)%dotState (2*prm%totalNslip+1: 3*prm%totalNslip,:) + del%rho_sgl_mob_scr_pos => plasticState(p)%deltaState (2*prm%totalNslip+1: 3*prm%totalNslip,:) - stt%rho_sgl_mob_scr_neg => plasticState(p)%state (3*prm%totalNslip+1: 4*prm%totalNslip,:) - dot%rho_sgl_mob_scr_neg => plasticState(p)%dotState (3*prm%totalNslip+1: 4*prm%totalNslip,:) - del%rho_sgl_mob_scr_neg => plasticState(p)%deltaState (3*prm%totalNslip+1: 4*prm%totalNslip,:) + stt%rho_sgl_mob_scr_neg => plasticState(p)%state (3*prm%totalNslip+1: 4*prm%totalNslip,:) + dot%rho_sgl_mob_scr_neg => plasticState(p)%dotState (3*prm%totalNslip+1: 4*prm%totalNslip,:) + del%rho_sgl_mob_scr_neg => plasticState(p)%deltaState (3*prm%totalNslip+1: 4*prm%totalNslip,:) stt%rhoSglImmobile => plasticState(p)%state (4*prm%totalNslip+1: 8*prm%totalNslip,:) dot%rhoSglImmobile => plasticState(p)%dotState (4*prm%totalNslip+1: 8*prm%totalNslip,:) - del%rhoSglImmobile => plasticState(p)%deltaState (4*prm%totalNslip+1: 8*prm%totalNslip,:) + del%rhoSglImmobile => plasticState(p)%deltaState (4*prm%totalNslip+1: 8*prm%totalNslip,:) - stt%rho_sgl_imm_edg_pos => plasticState(p)%state (4*prm%totalNslip+1: 5*prm%totalNslip,:) - dot%rho_sgl_imm_edg_pos => plasticState(p)%dotState (4*prm%totalNslip+1: 5*prm%totalNslip,:) + stt%rho_sgl_imm_edg_pos => plasticState(p)%state (4*prm%totalNslip+1: 5*prm%totalNslip,:) + dot%rho_sgl_imm_edg_pos => plasticState(p)%dotState (4*prm%totalNslip+1: 5*prm%totalNslip,:) del%rho_sgl_imm_edg_pos => plasticState(p)%deltaState (4*prm%totalNslip+1: 5*prm%totalNslip,:) - stt%rho_sgl_imm_edg_neg => plasticState(p)%state (5*prm%totalNslip+1: 6*prm%totalNslip,:) - dot%rho_sgl_imm_edg_neg => plasticState(p)%dotState (5*prm%totalNslip+1: 6*prm%totalNslip,:) + stt%rho_sgl_imm_edg_neg => plasticState(p)%state (5*prm%totalNslip+1: 6*prm%totalNslip,:) + dot%rho_sgl_imm_edg_neg => plasticState(p)%dotState (5*prm%totalNslip+1: 6*prm%totalNslip,:) del%rho_sgl_imm_edg_neg => plasticState(p)%deltaState (5*prm%totalNslip+1: 6*prm%totalNslip,:) - stt%rho_sgl_imm_scr_pos => plasticState(p)%state (6*prm%totalNslip+1: 7*prm%totalNslip,:) - dot%rho_sgl_imm_scr_pos => plasticState(p)%dotState(6*prm%totalNslip+1: 7*prm%totalNslip,:) - del%rho_sgl_imm_scr_pos => plasticState(p)%deltaState(6*prm%totalNslip+1: 7*prm%totalNslip,:) + stt%rho_sgl_imm_scr_pos => plasticState(p)%state (6*prm%totalNslip+1: 7*prm%totalNslip,:) + dot%rho_sgl_imm_scr_pos => plasticState(p)%dotState (6*prm%totalNslip+1: 7*prm%totalNslip,:) + del%rho_sgl_imm_scr_pos => plasticState(p)%deltaState (6*prm%totalNslip+1: 7*prm%totalNslip,:) - stt%rho_sgl_imm_scr_neg => plasticState(p)%state (7*prm%totalNslip+1: 8*prm%totalNslip,:) - dot%rho_sgl_imm_scr_neg => plasticState(p)%dotState(7*prm%totalNslip+1: 8*prm%totalNslip,:) - del%rho_sgl_imm_scr_neg => plasticState(p)%deltaState(7*prm%totalNslip+1: 8*prm%totalNslip,:) + stt%rho_sgl_imm_scr_neg => plasticState(p)%state (7*prm%totalNslip+1: 8*prm%totalNslip,:) + dot%rho_sgl_imm_scr_neg => plasticState(p)%dotState (7*prm%totalNslip+1: 8*prm%totalNslip,:) + del%rho_sgl_imm_scr_neg => plasticState(p)%deltaState (7*prm%totalNslip+1: 8*prm%totalNslip,:) stt%rhoDip => plasticState(p)%state (8*prm%totalNslip+1:10*prm%totalNslip,:) dot%rhoDip => plasticState(p)%dotState (8*prm%totalNslip+1:10*prm%totalNslip,:) - del%rhoDip => plasticState(p)%deltaState (8*prm%totalNslip+1:10*prm%totalNslip,:) + del%rhoDip => plasticState(p)%deltaState (8*prm%totalNslip+1:10*prm%totalNslip,:) - stt%rho_dip_edg => plasticState(p)%state (8*prm%totalNslip+1: 9*prm%totalNslip,:) - dot%rho_dip_edg => plasticState(p)%dotState (8*prm%totalNslip+1: 9*prm%totalNslip,:) - del%rho_dip_edg => plasticState(p)%deltaState (8*prm%totalNslip+1: 9*prm%totalNslip,:) + stt%rho_dip_edg => plasticState(p)%state (8*prm%totalNslip+1: 9*prm%totalNslip,:) + dot%rho_dip_edg => plasticState(p)%dotState (8*prm%totalNslip+1: 9*prm%totalNslip,:) + del%rho_dip_edg => plasticState(p)%deltaState (8*prm%totalNslip+1: 9*prm%totalNslip,:) stt%rho_dip_scr => plasticState(p)%state (9*prm%totalNslip+1:10*prm%totalNslip,:) dot%rho_dip_scr => plasticState(p)%dotState (9*prm%totalNslip+1:10*prm%totalNslip,:) - del%rho_dip_scr => plasticState(p)%deltaState (9*prm%totalNslip+1:10*prm%totalNslip,:) + del%rho_dip_scr => plasticState(p)%deltaState (9*prm%totalNslip+1:10*prm%totalNslip,:) - stt%accumulatedshear => plasticState(p)%state (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) - dot%accumulatedshear => plasticState(p)%dotState (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) - del%accumulatedshear => plasticState(p)%deltaState (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) + stt%gamma => plasticState(p)%state (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) + dot%gamma => plasticState(p)%dotState (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) + del%gamma => plasticState(p)%deltaState (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) plasticState(p)%aTolState(10*prm%totalNslip + 1:11*prm%totalNslip ) = prm%aTolShear - plasticState(p)%slipRate => plasticState(p)%dotState(10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) - plasticState(p)%accumulatedSlip => plasticState(p)%state (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) + plasticState(p)%slipRate => plasticState(p)%dotState (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) + plasticState(p)%accumulatedSlip => plasticState(p)%state(10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) - stt%rho_forest => plasticState(p)%state (11*prm%totalNslip + 1:12*prm%totalNslip ,1:NofMyPhase) - stt%v => plasticState(p)%state (12*prm%totalNslip + 1:16*prm%totalNslip ,1:NofMyPhase) + stt%rho_forest => plasticState(p)%state (11*prm%totalNslip + 1:12*prm%totalNslip ,1:NofMyPhase) + stt%v => plasticState(p)%state (12*prm%totalNslip + 1:16*prm%totalNslip ,1:NofMyPhase) + stt%v_edg_pos => plasticState(p)%state (12*prm%totalNslip + 1:13*prm%totalNslip ,1:NofMyPhase) + stt%v_edg_neg => plasticState(p)%state (13*prm%totalNslip + 1:14*prm%totalNslip ,1:NofMyPhase) + stt%v_scr_pos => plasticState(p)%state (14*prm%totalNslip + 1:15*prm%totalNslip ,1:NofMyPhase) + stt%v_scr_neg => plasticState(p)%state (15*prm%totalNslip + 1:16*prm%totalNslip ,1:NofMyPhase) - allocate(dst%tau_Threshold(prm%totalNslip,NofMyPhase),source=0.0_pReal) - allocate(dst%tau_Back(prm%totalNslip,NofMyPhase),source=0.0_pReal) - - allocate(res%rhoDotFlux(prm%totalNslip,8,NofMyPhase),source=0.0_pReal) - allocate(res%rhoDotMultiplication(prm%totalNslip,2,NofMyPhase),source=0.0_pReal) - allocate(res%rhoDotSingle2DipoleGlide(prm%totalNslip,2,NofMyPhase),source=0.0_pReal) - allocate(res%rhoDotAthermalAnnihilation(prm%totalNslip,2,NofMyPhase),source=0.0_pReal) - allocate(res%rhoDotThermalAnnihilation(prm%totalNslip,2,NofMyPhase),source=0.0_pReal) - allocate(res%rhoDotEdgeJogs(prm%totalNslip,NofMyPhase),source=0.0_pReal) + allocate(dst%tau_pass(prm%totalNslip,NofMyPhase),source=0.0_pReal) + allocate(dst%tau_Back(prm%totalNslip,NofMyPhase), source=0.0_pReal) end associate - if (NofMyPhase > 0) call stateInit(p,NofMyPhase) plasticState(p)%state0 = plasticState(p)%state @@ -903,7 +843,7 @@ subroutine plastic_nonlocal_dependentState(Fe, Fp, ip, el) endif forall (s = 1:ns) & - dst%tau_threshold(s,of) = prm%mu * prm%burgers(s) & + dst%tau_pass(s,of) = prm%mu * prm%burgers(s) & * sqrt(dot_product(sum(abs(rho),2), myInteractionMatrix(1:ns,s))) @@ -948,8 +888,8 @@ subroutine plastic_nonlocal_dependentState(Fe, Fp, ip, el) neighbor_rhoTotal(1,:,n) = sum(abs(rho_neighbor(:,edg)),2) neighbor_rhoTotal(2,:,n) = sum(abs(rho_neighbor(:,scr)),2) - connection_latticeConf(1:3,n) = matmul(invFe, mesh_ipCoordinates(1:3,neighbor_ip,neighbor_el) & - - mesh_ipCoordinates(1:3,ip,el)) + connection_latticeConf(1:3,n) = matmul(invFe, discretization_IPcoords(1:3,neighbor_el+neighbor_ip-1) & + - discretization_IPcoords(1:3,el+neighbor_ip-1)) normal_latticeConf = matmul(transpose(invFp), IPareaNormal(1:3,n,ip,el)) if (math_inner(normal_latticeConf,connection_latticeConf(1:3,n)) < 0.0_pReal) & ! neighboring connection points in opposite direction to face normal: must be periodic image connection_latticeConf(1:3,n) = normal_latticeConf * IPvolume(ip,el)/IParea(n,ip,el) ! instead take the surface normal scaled with the diameter of the cell @@ -1020,7 +960,7 @@ subroutine plastic_nonlocal_dependentState(Fe, Fp, ip, el) .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0)) then write(6,'(/,a,i8,1x,i2,1x,i1,/)') '<< CONST >> nonlocal_microstructure at el ip ',el,ip write(6,'(a,/,12x,12(e10.3,1x))') '<< CONST >> rhoForest', stt%rho_forest(:,of) - write(6,'(a,/,12x,12(f10.5,1x))') '<< CONST >> tauThreshold / MPa', dst%tau_threshold(:,of)*1e-6 + write(6,'(a,/,12x,12(f10.5,1x))') '<< CONST >> tauThreshold / MPa', dst%tau_pass(:,of)*1e-6 write(6,'(a,/,12x,12(f10.5,1x),/)') '<< CONST >> tauBack / MPa', dst%tau_back(:,of)*1e-6 endif #endif @@ -1219,7 +1159,7 @@ subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, & of = material_phasememberAt(1,ip,el) instance = phase_plasticityInstance(ph) - associate(prm => param(instance),dst=>microstructure(instance)) + associate(prm => param(instance),dst=>microstructure(instance),stt=>state(instance)) ns = prm%totalNslip !*** shortcut to state variables @@ -1250,7 +1190,7 @@ subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, & ! edges call plastic_nonlocal_kinetics(v(1:ns,1), dv_dtau(1:ns,1), dv_dtauNS(1:ns,1), & - tau(1:ns), tauNS(1:ns,1), dst%tau_Threshold(1:ns,of), & + tau(1:ns), tauNS(1:ns,1), dst%tau_pass(1:ns,of), & 1, Temperature, instance, of) v(1:ns,2) = v(1:ns,1) dv_dtau(1:ns,2) = dv_dtau(1:ns,1) @@ -1266,15 +1206,12 @@ subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, & else do t = 3,4 call plastic_nonlocal_kinetics(v(1:ns,t), dv_dtau(1:ns,t), dv_dtauNS(1:ns,t), & - tau(1:ns), tauNS(1:ns,t), dst%tau_Threshold(1:ns,of), & + tau(1:ns), tauNS(1:ns,t), dst%tau_pass(1:ns,of), & 2 , Temperature, instance, of) enddo endif - - - !*** store velocity in state - forall (t = 1:4) & - plasticState(ph)%state(iV(1:ns,t,instance),of) = v(1:ns,t) + + stt%v(:,of) = pack(v,.true.) !*** Bauschinger effect forall (s = 1:ns, t = 5:8, rhoSgl(s,t) * v(s,t-4) < 0.0_pReal) & @@ -1516,7 +1453,10 @@ subroutine plastic_nonlocal_dotState(Mp, Fe, Fp, Temperature, & ph = material_phaseAt(1,el) instance = phase_plasticityInstance(ph) - associate(prm => param(instance),dst => microstructure(instance),dot => dotState(instance),stt => state(instance)) + associate(prm => param(instance), & + dst => microstructure(instance), & + dot => dotState(instance), & + stt => state(instance)) ns = totalNslip(instance) tau = 0.0_pReal @@ -1666,11 +1606,11 @@ subroutine plastic_nonlocal_dotState(Mp, Fe, Fp, Temperature, & endif enteringFlux: if (considerEnteringFlux) then - forall (s = 1:ns, t = 1:4) - neighbor_v(s,t) = plasticState(np)%state(iV (s,t,neighbor_instance),no) - neighbor_rhoSgl(s,t) = max(plasticState(np)%state(iRhoU(s,t,neighbor_instance),no), & + forall (s = 1:ns, t = 1:4) + neighbor_v(s,t) = plasticState(np)%state(iV (s,t,neighbor_instance),no) + neighbor_rhoSgl(s,t) = max(plasticState(np)%state(iRhoU(s,t,neighbor_instance),no), & 0.0_pReal) - endforall + endforall where (neighbor_rhoSgl * IPvolume(neighbor_ip,neighbor_el) ** 0.667_pReal < prm%significantN & .or. neighbor_rhoSgl < prm%significantRho) & @@ -1818,14 +1758,6 @@ subroutine plastic_nonlocal_dotState(Mp, Fe, Fp, Temperature, & + rhoDotSingle2DipoleGlide & + rhoDotAthermalAnnihilation & + rhoDotThermalAnnihilation - - results(instance)%rhoDotFlux(1:ns,1:8,o) = rhoDotFlux(1:ns,1:8) - results(instance)%rhoDotMultiplication(1:ns,1:2,o) = rhoDotMultiplication(1:ns,[1,3]) - results(instance)%rhoDotSingle2DipoleGlide(1:ns,1:2,o) = rhoDotSingle2DipoleGlide(1:ns,9:10) - results(instance)%rhoDotAthermalAnnihilation(1:ns,1:2,o) = rhoDotAthermalAnnihilation(1:ns,9:10) - results(instance)%rhoDotThermalAnnihilation(1:ns,1:2,o) = rhoDotThermalAnnihilation(1:ns,9:10) - results(instance)%rhoDotEdgeJogs(1:ns,o) = 2.0_pReal * rhoDotThermalAnnihilation(1:ns,1) - #ifdef DEBUG if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0 & @@ -1861,14 +1793,9 @@ subroutine plastic_nonlocal_dotState(Mp, Fe, Fp, Temperature, & #endif plasticState(p)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) else - forall (s = 1:ns, t = 1:4) - plasticState(p)%dotState(iRhoU(s,t,instance),o) = rhoDot(s,t) - plasticState(p)%dotState(iRhoB(s,t,instance),o) = rhoDot(s,t+4) - endforall - forall (s = 1:ns, c = 1:2) & - plasticState(p)%dotState(iRhoD(s,c,instance),o) = rhoDot(s,c+8) + dot%rho(:,o) = pack(rhoDot,.true.) forall (s = 1:ns) & - dot%accumulatedshear(s,o) = sum(gdot(s,1:4)) + dot%gamma(s,o) = sum(gdot(s,1:4)) endif end associate @@ -1902,8 +1829,6 @@ subroutine plastic_nonlocal_updateCompatibility(orientation,i,e) ns, & ! number of active slip systems s1, & ! slip system index (me) s2 ! slip system index (my neighbor) - real(pReal), dimension(4) :: & - absoluteMisorientation ! absolute misorientation (without symmetry) between me and my neighbor real(pReal), dimension(2,totalNslip(phase_plasticityInstance(material_phaseAt(1,e))),& totalNslip(phase_plasticityInstance(material_phaseAt(1,e))),& nIPneighbors) :: & @@ -1914,7 +1839,7 @@ subroutine plastic_nonlocal_updateCompatibility(orientation,i,e) nThresholdValues logical, dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,e)))) :: & belowThreshold - type(rotation) :: rot + type(rotation) :: mis Nneighbors = nIPneighbors ph = material_phaseAt(1,e) @@ -1980,18 +1905,17 @@ subroutine plastic_nonlocal_updateCompatibility(orientation,i,e) !* Finally the smallest compatibility value is decreased until the sum is exactly equal to one. !* All values below the threshold are set to zero. else - rot = orientation(1,i,e)%misorientation(orientation(1,neighbor_i,neighbor_e)) - absoluteMisorientation = rot%asQuaternion() + mis = orientation(1,i,e)%misorientation(orientation(1,neighbor_i,neighbor_e)) mySlipSystems: do s1 = 1,ns neighborSlipSystems: do s2 = 1,ns my_compatibility(1,s2,s1,n) = math_inner(prm%slip_normal(1:3,s1), & - math_qRot(absoluteMisorientation, prm%slip_normal(1:3,s2))) & + mis%rotate(prm%slip_normal(1:3,s2))) & * abs(math_inner(prm%slip_direction(1:3,s1), & - math_qRot(absoluteMisorientation, prm%slip_direction(1:3,s2)))) + mis%rotate(prm%slip_direction(1:3,s2)))) my_compatibility(2,s2,s1,n) = abs(math_inner(prm%slip_normal(1:3,s1), & - math_qRot(absoluteMisorientation, prm%slip_normal(1:3,s2)))) & + mis%rotate(prm%slip_normal(1:3,s2)))) & * abs(math_inner(prm%slip_direction(1:3,s1), & - math_qRot(absoluteMisorientation, prm%slip_direction(1:3,s2)))) + mis%rotate(prm%slip_direction(1:3,s2)))) enddo neighborSlipSystems my_compatibilitySum = 0.0_pReal @@ -2021,206 +1945,6 @@ subroutine plastic_nonlocal_updateCompatibility(orientation,i,e) end subroutine plastic_nonlocal_updateCompatibility -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function plastic_nonlocal_postResults(ph,instance,of) result(postResults) - - integer, intent(in) :: & - ph, & - instance, & - of - - real(pReal), dimension(sum(plastic_nonlocal_sizePostResult(:,instance))) :: & - postResults - - integer :: & - ns, & !< short notation for the total number of active slip systems - c, & !< character of dislocation - cs, & !< constitutive result index - o, & !< index of current output - t, & !< type of dislocation - s !< index of my current slip system - - real(pReal), dimension(param(instance)%totalNslip,8) :: & - rhoSgl, & - rhoDotSgl !< evolution rate of single dislocation densities (positive/negative screw and edge without dipoles) - real(pReal), dimension(param(instance)%totalNslip,4) :: & - gdot, & !< shear rates - v !< velocities - real(pReal), dimension(param(instance)%totalNslip,2) :: & - rhoDotDip !< evolution rate of dipole dislocation densities (screw and edge dipoles) - - -ns = param(instance)%totalNslip - -cs = 0 - -associate(prm => param(instance),dst => microstructure(instance),stt=>state(instance),dot => dotState(instance)) - -forall (s = 1:ns, t = 1:4) - rhoSgl(s,t+4) = plasticState(ph)%State(iRhoB(s,t,instance),of) - v(s,t) = plasticState(ph)%State(iV(s,t,instance),of) - rhoDotSgl(s,t+4) = plasticState(ph)%dotState(iRhoB(s,t,instance),of) -endforall -forall (s = 1:ns, c = 1:2) - rhoDotDip(s,c) = plasticState(ph)%dotState(iRhoD(s,c,instance),of) -endforall - -!* Calculate shear rate - -forall (t = 1:4) & - gdot(1:ns,t) = rhoSgl(1:ns,t) * prm%burgers(1:ns) * v(1:ns,t) - - -!* calculate limits for stable dipole height - - -outputsLoop: do o = 1,size(param(instance)%outputID) - select case(param(instance)%outputID(o)) - - case (rho_sgl_mob_edg_pos_ID) - postResults(cs+1:cs+ns) = stt%rho_sgl_mob_edg_pos(:,of) - cs = cs + ns - - case (rho_sgl_imm_edg_pos_ID) - postResults(cs+1:cs+ns) = stt%rho_sgl_imm_edg_pos(:,of) - cs = cs + ns - - case (rho_sgl_mob_edg_neg_ID) - postResults(cs+1:cs+ns) = stt%rho_sgl_mob_edg_neg(:,of) - cs = cs + ns - - case (rho_sgl_imm_edg_neg_ID) - postResults(cs+1:cs+ns) = stt%rho_sgl_imm_edg_neg(:,of) - cs = cs + ns - - case (rho_dip_edg_ID) - postResults(cs+1:cs+ns) = stt%rho_dip_edg(:,of) - cs = cs + ns - - case (rho_sgl_mob_scr_pos_ID) - postResults(cs+1:cs+ns) = stt%rho_sgl_mob_scr_pos(:,of) - cs = cs + ns - - case (rho_sgl_imm_scr_pos_ID) - postResults(cs+1:cs+ns) = stt%rho_sgl_imm_scr_pos(:,of) - cs = cs + ns - - case (rho_sgl_mob_scr_neg_ID) - postResults(cs+1:cs+ns) = stt%rho_sgl_mob_scr_neg(:,of) - cs = cs + ns - - case (rho_sgl_imm_scr_neg_ID) - postResults(cs+1:cs+ns) = stt%rho_sgl_imm_scr_neg(:,of) - cs = cs + ns - - case (rho_dip_scr_ID) - postResults(cs+1:cs+ns) = stt%rho_dip_scr(:,of) - cs = cs + ns - - case (rho_forest_ID) - postResults(cs+1:cs+ns) = stt%rho_forest(:,of) - cs = cs + ns - - case (shearrate_ID) - postResults(cs+1:cs+ns) = sum(gdot,2) - cs = cs + ns - - case (resolvedstress_back_ID) - postResults(cs+1:cs+ns) = dst%tau_back(:,of) - cs = cs + ns - - case (resistance_ID) - postResults(cs+1:cs+ns) = dst%tau_Threshold(:,of) - cs = cs + ns - - case (rho_dot_sgl_ID) - postResults(cs+1:cs+ns) = sum(rhoDotSgl(1:ns,1:4),2) & - + sum(rhoDotSgl(1:ns,5:8)*sign(1.0_pReal,rhoSgl(1:ns,5:8)),2) - cs = cs + ns - - case (rho_dot_sgl_mobile_ID) - postResults(cs+1:cs+ns) = sum(rhoDotSgl(1:ns,1:4),2) - cs = cs + ns - - case (rho_dot_dip_ID) - postResults(cs+1:cs+ns) = sum(rhoDotDip,2) - cs = cs + ns - - case (rho_dot_gen_edge_ID) - postResults(cs+1:cs+ns) = results(instance)%rhoDotMultiplication(1:ns,1,of) - cs = cs + ns - - case (rho_dot_gen_screw_ID) - postResults(cs+1:cs+ns) = results(instance)%rhoDotMultiplication(1:ns,2,of) - cs = cs + ns - - case (rho_dot_sgl2dip_edge_ID) - postResults(cs+1:cs+ns) = results(instance)%rhoDotSingle2DipoleGlide(1:ns,1,of) - cs = cs + ns - - case (rho_dot_sgl2dip_screw_ID) - postResults(cs+1:cs+ns) = results(instance)%rhoDotSingle2DipoleGlide(1:ns,2,of) - cs = cs + ns - - case (rho_dot_ann_ath_ID) - postResults(cs+1:cs+ns) = results(instance)%rhoDotAthermalAnnihilation(1:ns,1,of) & - + results(instance)%rhoDotAthermalAnnihilation(1:ns,2,of) - cs = cs + ns - - case (rho_dot_ann_the_edge_ID) - postResults(cs+1:cs+ns) = results(instance)%rhoDotThermalAnnihilation(1:ns,1,of) - cs = cs + ns - - case (rho_dot_ann_the_screw_ID) - postResults(cs+1:cs+ns) = results(instance)%rhoDotThermalAnnihilation(1:ns,2,of) - cs = cs + ns - - case (rho_dot_edgejogs_ID) - postResults(cs+1:cs+ns) = results(instance)%rhoDotEdgeJogs(1:ns,of) - cs = cs + ns - - case (rho_dot_flux_mobile_ID) - postResults(cs+1:cs+ns) = sum(results(instance)%rhoDotFlux(1:ns,1:4,of),2) - cs = cs + ns - - case (rho_dot_flux_edge_ID) - postResults(cs+1:cs+ns) = sum(results(instance)%rhoDotFlux(1:ns,1:2,of),2) & - + sum(results(instance)%rhoDotFlux(1:ns,5:6,of)*sign(1.0_pReal,rhoSgl(1:ns,5:6)),2) - cs = cs + ns - - case (rho_dot_flux_screw_ID) - postResults(cs+1:cs+ns) = sum(results(instance)%rhoDotFlux(1:ns,3:4,of),2) & - + sum(results(instance)%rhoDotFlux(1:ns,7:8,of)*sign(1.0_pReal,rhoSgl(1:ns,7:8)),2) - cs = cs + ns - - case (velocity_edge_pos_ID) - postResults(cs+1:cs+ns) = v(1:ns,1) - cs = cs + ns - - case (velocity_edge_neg_ID) - postResults(cs+1:cs+ns) = v(1:ns,2) - cs = cs + ns - - case (velocity_screw_pos_ID) - postResults(cs+1:cs+ns) = v(1:ns,3) - cs = cs + ns - - case (velocity_screw_neg_ID) - postResults(cs+1:cs+ns) = v(1:ns,4) - cs = cs + ns - - case(accumulatedshear_ID) - postResults(cs+1:cs+ns) = stt%accumulatedshear(:,of) - cs = cs + ns - - end select -enddo outputsLoop -end associate -end function plastic_nonlocal_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief returns copy of current dislocation densities from state !> @details raw values is rectified @@ -2234,7 +1958,7 @@ function getRho(instance,of,ip,el) getRho = reshape(state(instance)%rho(:,of),[prm%totalNslip,10]) - ! ensure mobile densities (not for imm, they have a sign) + ! ensure positive densities (not for imm, they have a sign) getRho(:,mob) = max(getRho(:,mob),0.0_pReal) getRho(:,dip) = max(getRho(:,dip),0.0_pReal) @@ -2258,7 +1982,7 @@ subroutine plastic_nonlocal_results(instance,group) character(len=*) :: group integer :: o - associate(prm => param(instance), stt => state(instance)) + associate(prm => param(instance),dst => microstructure(instance),stt=>state(instance)) outputsLoop: do o = 1,size(prm%outputID) select case(prm%outputID(o)) case (rho_sgl_mob_edg_pos_ID) @@ -2294,6 +2018,24 @@ subroutine plastic_nonlocal_results(instance,group) case (rho_forest_ID) call results_writeDataset(group,stt%rho_forest, 'rho_forest',& 'forest density','1/m²') + case (v_edg_pos_ID) + call results_writeDataset(group,stt%v_edg_pos, 'v_edg_pos',& + 'positive edge velocity','m/s') + case (v_edg_neg_ID) + call results_writeDataset(group,stt%v_edg_neg, 'v_edg_neg',& + 'negative edge velocity','m/s') + case (v_scr_pos_ID) + call results_writeDataset(group,stt%v_scr_pos, 'v_scr_pos',& + 'positive srew velocity','m/s') + case (v_scr_neg_ID) + call results_writeDataset(group,stt%v_scr_neg, 'v_scr_neg',& + 'negative screw velocity','m/s') + case(gamma_ID) + call results_writeDataset(group,stt%gamma,'gamma',& + 'plastic shear','1') + case (tau_pass_ID) + call results_writeDataset(group,dst%tau_pass,'tau_pass',& + 'passing stress for slip','Pa') end select enddo outputsLoop end associate diff --git a/src/plastic_phenopowerlaw.f90 b/src/plastic_phenopowerlaw.f90 index 48b49c3af..b8f5c8306 100644 --- a/src/plastic_phenopowerlaw.f90 +++ b/src/plastic_phenopowerlaw.f90 @@ -17,11 +17,6 @@ module plastic_phenopowerlaw implicit none private - - integer, dimension(:,:), allocatable, target, public :: & - plastic_phenopowerlaw_sizePostResult !< size of each post result output - character(len=64), dimension(:,:), allocatable, target, public :: & - plastic_phenopowerlaw_output !< name of each post result output enum, bind(c) enumerator :: & @@ -100,7 +95,6 @@ module plastic_phenopowerlaw plastic_phenopowerlaw_init, & plastic_phenopowerlaw_LpAndItsTangent, & plastic_phenopowerlaw_dotState, & - plastic_phenopowerlaw_postResults, & plastic_phenopowerlaw_results contains @@ -137,10 +131,6 @@ subroutine plastic_phenopowerlaw_init if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance - allocate(plastic_phenopowerlaw_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(plastic_phenopowerlaw_output(maxval(phase_Noutput),Ninstance)) - plastic_phenopowerlaw_output = '' - allocate(param(Ninstance)) allocate(state(Ninstance)) allocate(dotState(Ninstance)) @@ -306,8 +296,6 @@ subroutine plastic_phenopowerlaw_init end select if (outputID /= undefined_ID) then - plastic_phenopowerlaw_output(i,phase_plasticityInstance(p)) = outputs(i) - plastic_phenopowerlaw_sizePostResult(i,phase_plasticityInstance(p)) = outputSize prm%outputID = [prm%outputID, outputID] endif @@ -322,7 +310,6 @@ subroutine plastic_phenopowerlaw_init call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0, & prm%totalNslip,prm%totalNtwin,0) - plasticState(p)%sizePostResults = sum(plastic_phenopowerlaw_sizePostResult(:,phase_plasticityInstance(p))) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -473,71 +460,6 @@ subroutine plastic_phenopowerlaw_dotState(Mp,instance,of) end subroutine plastic_phenopowerlaw_dotState -!-------------------------------------------------------------------------------------------------- -!> @brief return array of constitutive results -!-------------------------------------------------------------------------------------------------- -function plastic_phenopowerlaw_postResults(Mp,instance,of) result(postResults) - - real(pReal), dimension(3,3), intent(in) :: & - Mp !< Mandel stress - integer, intent(in) :: & - instance, & - of - - real(pReal), dimension(sum(plastic_phenopowerlaw_sizePostResult(:,instance))) :: & - postResults - - integer :: & - o,c,i - real(pReal), dimension(param(instance)%totalNslip) :: & - gdot_slip_pos,gdot_slip_neg - - c = 0 - - associate(prm => param(instance), stt => state(instance)) - - outputsLoop: do o = 1,size(prm%outputID) - select case(prm%outputID(o)) - - case (resistance_slip_ID) - postResults(c+1:c+prm%totalNslip) = stt%xi_slip(1:prm%totalNslip,of) - c = c + prm%totalNslip - case (accumulatedshear_slip_ID) - postResults(c+1:c+prm%totalNslip) = stt%gamma_slip(1:prm%totalNslip,of) - c = c + prm%totalNslip - case (shearrate_slip_ID) - call kinetics_slip(Mp,instance,of,gdot_slip_pos,gdot_slip_neg) - postResults(c+1:c+prm%totalNslip) = gdot_slip_pos+gdot_slip_neg - c = c + prm%totalNslip - case (resolvedstress_slip_ID) - do i = 1, prm%totalNslip - postResults(c+i) = math_mul33xx33(Mp,prm%Schmid_slip(1:3,1:3,i)) - enddo - c = c + prm%totalNslip - - case (resistance_twin_ID) - postResults(c+1:c+prm%totalNtwin) = stt%xi_twin(1:prm%totalNtwin,of) - c = c + prm%totalNtwin - case (accumulatedshear_twin_ID) - postResults(c+1:c+prm%totalNtwin) = stt%gamma_twin(1:prm%totalNtwin,of) - c = c + prm%totalNtwin - case (shearrate_twin_ID) - call kinetics_twin(Mp,instance,of,postResults(c+1:c+prm%totalNtwin)) - c = c + prm%totalNtwin - case (resolvedstress_twin_ID) - do i = 1, prm%totalNtwin - postResults(c+i) = math_mul33xx33(Mp,prm%Schmid_twin(1:3,1:3,i)) - enddo - c = c + prm%totalNtwin - - end select - enddo outputsLoop - - end associate - -end function plastic_phenopowerlaw_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- diff --git a/src/prec.f90 b/src/prec.f90 index f0475e9b6..b6d5d4fdf 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -62,10 +62,6 @@ module prec end type type, extends(tState), public :: tPlasticState - integer :: & - nSlip = 0, & - nTwin = 0, & - nTrans = 0 logical :: & nonlocal = .false. real(pReal), pointer, dimension(:,:) :: & diff --git a/src/quit.f90 b/src/quit.f90 index 5f492de36..146071600 100644 --- a/src/quit.f90 +++ b/src/quit.f90 @@ -42,7 +42,6 @@ subroutine quit(stop_id) dateAndTime(7) if (stop_id == 0 .and. ierr == 0 .and. error == 0) stop 0 ! normal termination - if (stop_id == 2 .and. ierr == 0 .and. error == 0) stop 2 ! not all incs converged stop 1 ! error (message from IO_error) end subroutine quit diff --git a/src/results.f90 b/src/results.f90 index 93351c5f2..9a3261e94 100644 --- a/src/results.f90 +++ b/src/results.f90 @@ -50,6 +50,7 @@ module results results_addIncrement, & results_addGroup, & results_openGroup, & + results_closeGroup, & results_writeDataset, & results_setLink, & results_addAttribute, & @@ -68,10 +69,9 @@ subroutine results_init write(6,'(a)') ' https://doi.org/10.1007/s40192-017-0084-5' resultsFile = HDF5_openFile(trim(getSolverJobName())//'.hdf5','w',.true.) - call HDF5_addAttribute(resultsFile,'DADF5-version',0.2) - call HDF5_addAttribute(resultsFile,'DADF5-major',0) - call HDF5_addAttribute(resultsFile,'DADF5-minor',2) - call HDF5_addAttribute(resultsFile,'DAMASK',DAMASKVERSION) + call HDF5_addAttribute(resultsFile,'DADF5_version_major',0) + call HDF5_addAttribute(resultsFile,'DADF5_version_minor',4) + call HDF5_addAttribute(resultsFile,'DAMASK_version',DAMASKVERSION) call get_command(commandLine) call HDF5_addAttribute(resultsFile,'call',trim(commandLine)) call HDF5_closeGroup(results_addGroup('mapping')) @@ -110,7 +110,7 @@ subroutine results_addIncrement(inc,time) real(pReal), intent(in) :: time character(len=pStringLen) :: incChar - write(incChar,'(i5.5)') inc ! allow up to 99999 increments + write(incChar,'(i10)') inc call HDF5_closeGroup(results_addGroup(trim('inc'//trim(adjustl(incChar))))) call results_setLink(trim('inc'//trim(adjustl(incChar))),'current') call HDF5_addAttribute(resultsFile,'time/s',time,trim('inc'//trim(adjustl(incChar)))) @@ -120,6 +120,7 @@ subroutine results_addIncrement(inc,time) end subroutine results_addIncrement + !-------------------------------------------------------------------------------------------------- !> @brief open a group from the results file !-------------------------------------------------------------------------------------------------- @@ -144,6 +145,18 @@ integer(HID_T) function results_addGroup(groupName) end function results_addGroup +!-------------------------------------------------------------------------------------------------- +!> @brief close a group +!-------------------------------------------------------------------------------------------------- +subroutine results_closeGroup(group_id) + + integer(HID_T), intent(in) :: group_id + + call HDF5_closeGroup(group_id) + +end subroutine results_closeGroup + + !-------------------------------------------------------------------------------------------------- !> @brief set link to object in results file !-------------------------------------------------------------------------------------------------- @@ -304,18 +317,18 @@ subroutine results_writeTensorDataset_real(group,dataset,label,description,SIuni real(pReal), intent(in), dimension(:,:,:) :: dataset integer :: i - logical :: T + logical :: transposed_ integer(HID_T) :: groupHandle real(pReal), dimension(:,:,:), allocatable :: dataset_transposed if(present(transposed)) then - T = transposed + transposed_ = transposed else - T = .true. + transposed_ = .true. endif - if(T) then + if(transposed_) then if(size(dataset,1) /= size(dataset,2)) call IO_error(0,ext_msg='transpose non-symmetric tensor') allocate(dataset_transposed,mold=dataset) do i=1,size(dataset_transposed,3) diff --git a/src/rotations.f90 b/src/rotations.f90 index 7e642ce27..a4a0bac88 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -64,6 +64,7 @@ module rotations procedure, public :: asRodrigues procedure, public :: asMatrix !------------------------------------------ + procedure, public :: fromQuaternion procedure, public :: fromEulers procedure, public :: fromAxisAngle procedure, public :: fromMatrix @@ -157,6 +158,18 @@ end function asHomochoric !--------------------------------------------------------------------------------------------------- ! Initialize rotation from different representations !--------------------------------------------------------------------------------------------------- +subroutine fromQuaternion(self,qu) + + class(rotation), intent(out) :: self + real(pReal), dimension(4), intent(in) :: qu + + if (dNeq(norm2(qu),1.0_pReal)) & + call IO_error(402,ext_msg='fromQuaternion') + + self%q = qu + +end subroutine fromQuaternion +!--------------------------------------------------------------------------------------------------- subroutine fromEulers(self,eu,degrees) class(rotation), intent(out) :: self @@ -381,18 +394,18 @@ pure function qu2om(qu) result(om) qq = qu(1)**2-sum(qu(2:4)**2) - om(1,1) = qq+2.0*qu(2)**2 - om(2,2) = qq+2.0*qu(3)**2 - om(3,3) = qq+2.0*qu(4)**2 + om(1,1) = qq+2.0_pReal*qu(2)**2 + om(2,2) = qq+2.0_pReal*qu(3)**2 + om(3,3) = qq+2.0_pReal*qu(4)**2 - om(1,2) = 2.0*(qu(2)*qu(3)-qu(1)*qu(4)) - om(2,3) = 2.0*(qu(3)*qu(4)-qu(1)*qu(2)) - om(3,1) = 2.0*(qu(4)*qu(2)-qu(1)*qu(3)) - om(2,1) = 2.0*(qu(3)*qu(2)+qu(1)*qu(4)) - om(3,2) = 2.0*(qu(4)*qu(3)+qu(1)*qu(2)) - om(1,3) = 2.0*(qu(2)*qu(4)+qu(1)*qu(3)) + om(1,2) = 2.0_pReal*(qu(2)*qu(3)-qu(1)*qu(4)) + om(2,3) = 2.0_pReal*(qu(3)*qu(4)-qu(1)*qu(2)) + om(3,1) = 2.0_pReal*(qu(4)*qu(2)-qu(1)*qu(3)) + om(2,1) = 2.0_pReal*(qu(3)*qu(2)+qu(1)*qu(4)) + om(3,2) = 2.0_pReal*(qu(4)*qu(3)+qu(1)*qu(2)) + om(1,3) = 2.0_pReal*(qu(2)*qu(4)+qu(1)*qu(3)) - if (P < 0.0) om = transpose(om) + if (P < 0.0_pReal) om = transpose(om) end function qu2om @@ -413,13 +426,13 @@ pure function qu2eu(qu) result(eu) chi = sqrt(q03*q12) degenerated: if (dEq0(chi)) then - eu = merge([atan2(-P*2.0*qu(1)*qu(4),qu(1)**2-qu(4)**2), 0.0_pReal, 0.0_pReal], & - [atan2( 2.0*qu(2)*qu(3),qu(2)**2-qu(3)**2), PI, 0.0_pReal], & + eu = merge([atan2(-P*2.0_pReal*qu(1)*qu(4),qu(1)**2-qu(4)**2), 0.0_pReal, 0.0_pReal], & + [atan2( 2.0_pReal*qu(2)*qu(3),qu(2)**2-qu(3)**2), PI, 0.0_pReal], & dEq0(q12)) else degenerated - chiInv = 1.0/chi + chiInv = 1.0_pReal/chi eu = [atan2((-P*qu(1)*qu(3)+qu(2)*qu(4))*chi, (-P*qu(1)*qu(2)-qu(3)*qu(4))*chi ), & - atan2( 2.0*chi, q03-q12 ), & + atan2( 2.0_pReal*chi, q03-q12 ), & atan2(( P*qu(1)*qu(3)+qu(2)*qu(4))*chi, (-P*qu(1)*qu(2)+qu(3)*qu(4))*chi )] endif degenerated where(eu<0.0_pReal) eu = mod(eu+2.0_pReal*PI,[2.0_pReal*PI,PI,2.0_pReal*PI]) @@ -492,11 +505,11 @@ pure function qu2ho(qu) result(ho) omega = 2.0 * acos(math_clip(qu(1),-1.0_pReal,1.0_pReal)) if (dEq0(omega)) then - ho = [ 0.0, 0.0, 0.0 ] + ho = [ 0.0_pReal, 0.0_pReal, 0.0_pReal ] else ho = qu(2:4) - f = 0.75 * ( omega - sin(omega) ) - ho = ho/norm2(ho)* f**(1.0/3.0) + f = 0.75_pReal * ( omega - sin(omega) ) + ho = ho/norm2(ho)* f**(1.0_pReal/3.0_pReal) end if end function qu2ho @@ -579,7 +592,7 @@ function om2ax(om) result(ax) ax(4) = acos(math_clip(t,-1.0_pReal,1.0_pReal)) if (dEq0(ax(4))) then - ax(1:3) = [ 0.0, 0.0, 1.0 ] + ax(1:3) = [ 0.0_pReal, 0.0_pReal, 1.0_pReal ] else call dgeev('N','V',3,om_,3,Wr,Wi,devNull,3,VR,3,work,size(work,1),ierr) if (ierr /= 0) call IO_error(0,ext_msg='Error in om2ax: DGEEV return not zero') @@ -704,19 +717,19 @@ pure function eu2ax(eu) result(ax) real(pReal) :: t, delta, tau, alpha, sigma - t = tan(eu(2)*0.5) - sigma = 0.5*(eu(1)+eu(3)) - delta = 0.5*(eu(1)-eu(3)) + t = tan(eu(2)*0.5_pReal) + sigma = 0.5_pReal*(eu(1)+eu(3)) + delta = 0.5_pReal*(eu(1)-eu(3)) tau = sqrt(t**2+sin(sigma)**2) - alpha = merge(PI, 2.0*atan(tau/cos(sigma)), dEq(sigma,PI*0.5_pReal,tol=1.0e-15_pReal)) + alpha = merge(PI, 2.0_pReal*atan(tau/cos(sigma)), dEq(sigma,PI*0.5_pReal,tol=1.0e-15_pReal)) if (dEq0(alpha)) then ! return a default identity axis-angle pair ax = [ 0.0_pReal, 0.0_pReal, 1.0_pReal, 0.0_pReal ] else ax(1:3) = -P/tau * [ t*cos(delta), t*sin(delta), sin(sigma) ] ! passive axis-angle pair so a minus sign in front ax(4) = alpha - if (alpha < 0.0) ax = -ax ! ensure alpha is positive + if (alpha < 0.0_pReal) ax = -ax ! ensure alpha is positive end if end function eu2ax @@ -737,7 +750,7 @@ pure function eu2ro(eu) result(ro) elseif(dEq0(ro(4))) then ro = [ 0.0_pReal, 0.0_pReal, P, 0.0_pReal ] else - ro(4) = tan(ro(4)*0.5) + ro(4) = tan(ro(4)*0.5_pReal) end if end function eu2ro @@ -786,8 +799,8 @@ pure function ax2qu(ax) result(qu) if (dEq0(ax(4))) then qu = [ 1.0_pReal, 0.0_pReal, 0.0_pReal, 0.0_pReal ] else - c = cos(ax(4)*0.5) - s = sin(ax(4)*0.5) + c = cos(ax(4)*0.5_pReal) + s = sin(ax(4)*0.5_pReal) qu = [ c, ax(1)*s, ax(2)*s, ax(3)*s ] end if @@ -807,7 +820,7 @@ pure function ax2om(ax) result(om) c = cos(ax(4)) s = sin(ax(4)) - omc = 1.0-c + omc = 1.0_pReal-c om(1,1) = ax(1)**2*omc + c om(2,2) = ax(2)**2*omc + c @@ -825,7 +838,7 @@ pure function ax2om(ax) result(om) om(3,1) = q + s*ax(2) om(1,3) = q - s*ax(2) - if (P > 0.0) om = transpose(om) + if (P > 0.0_pReal) om = transpose(om) end function ax2om @@ -853,14 +866,14 @@ pure function ax2ro(ax) result(ro) real(pReal), intent(in), dimension(4) :: ax real(pReal), dimension(4) :: ro - real(pReal), parameter :: thr = 1.0E-7 + real(pReal), parameter :: thr = 1.0e-7_pReal if (dEq0(ax(4))) then ro = [ 0.0_pReal, 0.0_pReal, P, 0.0_pReal ] else ro(1:3) = ax(1:3) ! we need to deal with the 180 degree case - ro(4) = merge(IEEE_value(ro(4),IEEE_positive_inf),tan(ax(4)*0.5 ),abs(ax(4)-PI) < thr) + ro(4) = merge(IEEE_value(ro(4),IEEE_positive_inf),tan(ax(4)*0.5_pReal),abs(ax(4)-PI) < thr) end if end function ax2ro @@ -877,8 +890,8 @@ pure function ax2ho(ax) result(ho) real(pReal) :: f - f = 0.75 * ( ax(4) - sin(ax(4)) ) - f = f**(1.0/3.0) + f = 0.75_pReal * ( ax(4) - sin(ax(4)) ) + f = f**(1.0_pReal/3.0_pReal) ho = ax(1:3) * f end function ax2ho @@ -956,10 +969,10 @@ pure function ro2ax(ro) result(ax) if (.not. IEEE_is_finite(ta)) then ax = [ ro(1), ro(2), ro(3), PI ] elseif (dEq0(ta)) then - ax = [ 0.0, 0.0, 1.0, 0.0 ] + ax = [ 0.0_pReal, 0.0_pReal, 1.0_pReal, 0.0_pReal ] else - angle = 2.0*atan(ta) - ta = 1.0/norm2(ro(1:3)) + angle = 2.0_pReal*atan(ta) + ta = 1.0_pReal/norm2(ro(1:3)) ax = [ ro(1)/ta, ro(2)/ta, ro(3)/ta, angle ] end if @@ -978,10 +991,10 @@ pure function ro2ho(ro) result(ho) real(pReal) :: f if (dEq0(norm2(ro(1:3)))) then - ho = [ 0.0, 0.0, 0.0 ] + ho = [ 0.0_pReal, 0.0_pReal, 0.0_pReal ] else - f = merge(2.0*atan(ro(4)) - sin(2.0*atan(ro(4))),PI, IEEE_is_finite(ro(4))) - ho = ro(1:3) * (0.75_pReal*f)**(1.0/3.0) + f = merge(2.0_pReal*atan(ro(4)) - sin(2.0_pReal*atan(ro(4))),PI, IEEE_is_finite(ro(4))) + ho = ro(1:3) * (0.75_pReal*f)**(1.0_pReal/3.0_pReal) end if end function ro2ho diff --git a/src/source_thermal_dissipation.f90 b/src/source_thermal_dissipation.f90 index 9b18efef5..0d16a9171 100644 --- a/src/source_thermal_dissipation.f90 +++ b/src/source_thermal_dissipation.f90 @@ -18,12 +18,6 @@ module source_thermal_dissipation source_thermal_dissipation_offset, & !< which source is my current thermal dissipation mechanism? source_thermal_dissipation_instance !< instance of thermal dissipation source mechanism - integer, dimension(:,:), allocatable, target, public :: & - source_thermal_dissipation_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - source_thermal_dissipation_output !< name of each post result output - type :: tParameters !< container type for internal constitutive parameters real(pReal) :: & kappa @@ -68,10 +62,6 @@ subroutine source_thermal_dissipation_init enddo enddo - allocate(source_thermal_dissipation_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(source_thermal_dissipation_output (maxval(phase_Noutput),Ninstance)) - source_thermal_dissipation_output = '' - do p=1, size(config_phase) if (all(phase_source(:,p) /= SOURCE_THERMAL_DISSIPATION_ID)) cycle instance = source_thermal_dissipation_instance(p) diff --git a/src/source_thermal_externalheat.f90 b/src/source_thermal_externalheat.f90 index 1b9d03529..00e6da6bf 100644 --- a/src/source_thermal_externalheat.f90 +++ b/src/source_thermal_externalheat.f90 @@ -15,17 +15,8 @@ module source_thermal_externalheat private integer, dimension(:), allocatable, public, protected :: & - source_thermal_externalheat_offset, & !< which source is my current thermal dissipation mechanism? - source_thermal_externalheat_instance !< instance of thermal dissipation source mechanism - - integer, dimension(:,:), allocatable, target, public :: & - source_thermal_externalheat_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - source_thermal_externalheat_output !< name of each post result output - - integer, dimension(:), allocatable, target, public :: & - source_thermal_externalheat_Noutput !< number of outputs per instance of this source + source_thermal_externalheat_offset, & !< which source is my current thermal dissipation mechanism? + source_thermal_externalheat_instance !< instance of thermal dissipation source mechanism type :: tParameters !< container type for internal constitutive parameters real(pReal), dimension(:), allocatable :: & @@ -73,11 +64,6 @@ subroutine source_thermal_externalheat_init enddo enddo - allocate(source_thermal_externalheat_sizePostResult(maxval(phase_Noutput),maxNinstance),source=0) - allocate(source_thermal_externalheat_output (maxval(phase_Noutput),maxNinstance)) - source_thermal_externalheat_output = '' - allocate(source_thermal_externalheat_Noutput(maxNinstance), source=0) - allocate(param(maxNinstance)) do p=1, size(config_phase) @@ -117,6 +103,7 @@ subroutine source_thermal_externalheat_dotState(phase, of) end subroutine source_thermal_externalheat_dotState + !-------------------------------------------------------------------------------------------------- !> @brief returns local heat generation rate !-------------------------------------------------------------------------------------------------- diff --git a/src/thermal_isothermal.f90 b/src/thermal_isothermal.f90 index 0271813e2..f06239944 100644 --- a/src/thermal_isothermal.f90 +++ b/src/thermal_isothermal.f90 @@ -31,7 +31,6 @@ subroutine thermal_isothermal_init if (thermal_type(homog) /= THERMAL_isothermal_ID) cycle NofMyHomog = count(material_homogenizationAt == homog) thermalState(homog)%sizeState = 0 - thermalState(homog)%sizePostResults = 0 allocate(thermalState(homog)%state0 (0,NofMyHomog), source=0.0_pReal) allocate(thermalState(homog)%subState0(0,NofMyHomog), source=0.0_pReal) allocate(thermalState(homog)%state (0,NofMyHomog), source=0.0_pReal)