diff --git a/.gitattributes b/.gitattributes index 9d1380127..66063d773 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12,12 +12,12 @@ *.pbz2 binary # ignore files from MSC.Marc in language statistics -install/MarcMentat/** linguist-vendored -src/Marc/include/* linguist-vendored +install/MarcMentat/** linguist-vendored +src/Marc/include/* linguist-vendored install/MarcMentat/MSC_modifications.py linguist-vendored=false # ignore reference files for tests in language statistics -python/tests/reference/** linguist-vendored +python/tests/resources/** linguist-vendored # ignore deprecated scripts -processing/legacy/** linguist-vendored +processing/legacy/** linguist-vendored diff --git a/.github/workflows/Fortran.yml b/.github/workflows/Fortran.yml index 3fa4426dc..9519d327d 100644 --- a/.github/workflows/Fortran.yml +++ b/.github/workflows/Fortran.yml @@ -2,7 +2,7 @@ name: Grid and Mesh Solver on: [push] env: - PETSC_VERSION: '3.18.1' + PETSC_VERSION: '3.18.4' HOMEBREW_NO_ANALYTICS: 'ON' # Make Homebrew installation a little quicker HOMEBREW_NO_AUTO_UPDATE: 'ON' HOMEBREW_NO_BOTTLE_SOURCE_FALLBACK: 'ON' @@ -11,14 +11,14 @@ env: jobs: - gcc: + gcc_ubuntu: - runs-on: ${{ matrix.os }} + runs-on: ubuntu-22.04 strategy: matrix: - os: [ubuntu-latest, macos-latest] - gcc_v: [9, 10, 11] # Version of GCC compilers + gcc_v: [9, 10, 11, 12] + fail-fast: false env: GCC_V: ${{ matrix.gcc_v }} @@ -27,8 +27,7 @@ jobs: - uses: actions/checkout@v3 - - name: GCC - Install (Linux) - if: contains( matrix.os, 'ubuntu') + - name: GCC - Install run: | sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update @@ -38,12 +37,6 @@ jobs: --slave /usr/bin/g++ g++ /usr/bin/g++-${GCC_V} \ --slave /usr/bin/gcov gcov /usr/bin/gcov-${GCC_V} - - name: GCC - Install (macOS) - if: contains( matrix.os, 'macos') - run: | - brew install gcc@${GCC_V} || brew upgrade gcc@${GCC_V} || true - brew link gcc@${GCC_V} - - name: PETSc - Cache download id: petsc-download uses: actions/cache@v3 @@ -63,28 +56,19 @@ jobs: export PETSC_ARCH=gcc${GCC_V} printenv >> $GITHUB_ENV - - name: PETSc - Cache installation + - name: PETSc - Cache Installation id: petsc-install uses: actions/cache@v3 with: path: petsc-${{ env.PETSC_VERSION }} - key: petsc-${{ env.PETSC_VERSION }}-${{ matrix.os }}-gcc${{ matrix.gcc_v }}-${{ hashFiles('**/petscversion.h') }} + key: petsc-${{ env.PETSC_VERSION }}-gcc${{ matrix.gcc_v }}-${{ hashFiles('**/petscversion.h') }} - - name: PETSc - Install (Linux) - if: contains( matrix.os, 'ubuntu') + - name: PETSc - Installation run: | cd petsc-${PETSC_VERSION} ./configure --with-fc=gfortran --with-cc=gcc --with-cxx=g++ \ - --download-mpich --download-fftw --download-hdf5 --download-hdf5-fortran-bindings=1 --download-zlib \ - --with-mpi-f90module-visibility=0 - make all - - - name: PETSc - Install (macOS) - if: contains( matrix.os, 'macos') - run: | - cd petsc-${PETSC_VERSION} - ./configure --with-fc=gfortran-${GCC_V} --with-cc=gcc-${GCC_V} --with-cxx=g++-${GCC_V} \ - --download-openmpi --download-fftw --download-hdf5 --download-hdf5-fortran-bindings=1 --download-zlib + --download-openmpi --download-fftw --download-hdf5 --download-hdf5-fortran-bindings=1 --download-zlib \ + --with-mpi-f90module-visibility=1 make all - name: DAMASK - Compile @@ -99,6 +83,8 @@ jobs: - name: DAMASK - Run run: | ./bin/DAMASK_grid -l tensionX.yaml -g 20grains16x16x16.vti -w examples/grid + ./bin/DAMASK_mesh -h + intel: @@ -107,6 +93,7 @@ jobs: strategy: matrix: intel_v: [classic, llvm] # Variant of Intel compilers + fail-fast: false env: INTEL_V: ${{ matrix.intel_v }} @@ -143,7 +130,7 @@ jobs: - name: PETSc - Prepare run: | tar -xf download/petsc-${PETSC_VERSION}.tar.gz -C . - sed -i "1715s/if not os.path.isfile(os.path.join(self.packageDir,'configure')):/if True:/g" \ + sed -i "1719s/if not os.path.isfile(os.path.join(self.packageDir,'configure')):/if True:/g" \ ./petsc-${PETSC_VERSION}/config/BuildSystem/config/package.py export PETSC_DIR=${PWD}/petsc-${PETSC_VERSION} export PETSC_ARCH=intel-${INTEL_V} @@ -179,6 +166,7 @@ jobs: make all - name: DAMASK - Compile + if: contains( matrix.intel_v, 'classic') run: | cmake -B build/grid -DDAMASK_SOLVER=grid -DCMAKE_INSTALL_PREFIX=${PWD} cmake --build build/grid --parallel @@ -187,6 +175,19 @@ jobs: cmake --build build/mesh --parallel cmake --install build/mesh + # ifx has issue with openMP + # https://community.intel.com/t5/Intel-Fortran-Compiler/ifx-ICE-and-SEGFAULT/m-p/1459877 + - name: DAMASK - Compile + if: contains( matrix.intel_v, 'llvm') + run: | + cmake -B build/grid -DDAMASK_SOLVER=grid -DCMAKE_INSTALL_PREFIX=${PWD} -DOPENMP=OFF + cmake --build build/grid --parallel + cmake --install build/grid + cmake -B build/mesh -DDAMASK_SOLVER=mesh -DCMAKE_INSTALL_PREFIX=${PWD} -DOPENMP=OFF + cmake --build build/mesh --parallel + cmake --install build/mesh + - name: DAMASK - Run run: | ./bin/DAMASK_grid -l tensionX.yaml -g 20grains16x16x16.vti -w examples/grid + ./bin/DAMASK_mesh -h diff --git a/.github/workflows/Python.yml b/.github/workflows/Python.yml index c630670a1..82f7dbb2e 100644 --- a/.github/workflows/Python.yml +++ b/.github/workflows/Python.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: - python-version: ['3.8', '3.9', '3.10'] + python-version: ['3.8', '3.9', '3.10', '3.11'] os: [ubuntu-latest, macos-latest, windows-latest] fail-fast: false @@ -75,7 +75,7 @@ jobs: run: > sudo apt-get update && sudo apt-get remove mysql* && - sudo apt-get install python3-pandas python3-scipy python3-h5py python3-vtk7 python3-matplotlib python3-yaml -y + sudo apt-get install python3-pandas python3-scipy python3-h5py python3-vtk9 python3-matplotlib python3-yaml -y - name: Run unit tests run: | diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8583c09c8..d24633468 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -181,13 +181,13 @@ open-source: script: - module load ${COMPILER_INTEL} ${MPI_INTEL} ${PETSC_INTEL} - cd PRIVATE/testing/pytest - - pytest -k 'not compile and not Marc' --basetemp ${TESTROOT}/open-source -v + - pytest -k 'not compile and not Marc' -m 'not cifail' --basetemp ${TESTROOT}/open-source -v Marc: stage: fortran script: - cd PRIVATE/testing/pytest - - pytest -k 'not compile and Marc' --damask-root=${TESTROOT} --basetemp ${TESTROOT}/Marc -v + - pytest -k 'not compile and Marc' -m 'not cifail' --damask-root=${TESTROOT} --basetemp ${TESTROOT}/Marc -v # Needs closer look # Phenopowerlaw_singleSlip: diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fb3f2d1b..de04a95e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ endif() project(Prerequisites LANGUAGES) set(ENV{PKG_CONFIG_PATH} "$ENV{PETSC_DIR}/$ENV{PETSC_ARCH}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") pkg_check_modules(PETSC_MIN REQUIRED PETSc>=3.12.0 QUIET) #CMake does not support version range -pkg_check_modules(PETSC REQUIRED PETSc<3.19.0) +pkg_check_modules(PETSC REQUIRED PETSc<3.20.0) pkg_get_variable(CMAKE_Fortran_COMPILER PETSc fcompiler) pkg_get_variable(CMAKE_C_COMPILER PETSc ccompiler) @@ -22,6 +22,8 @@ if(DAMASK_SOLVER STREQUAL "GRID") project(damask-grid HOMEPAGE_URL https://damask.mpie.de LANGUAGES Fortran C) elseif(DAMASK_SOLVER STREQUAL "MESH") project(damask-mesh HOMEPAGE_URL https://damask.mpie.de LANGUAGES Fortran C) +elseif(DAMASK_SOLVER STREQUAL "TEST") + project(damask-test HOMEPAGE_URL https://damask.mpie.de LANGUAGES Fortran C) else() message(FATAL_ERROR "Invalid solver: DAMASK_SOLVER=${DAMASK_SOLVER}") endif() @@ -90,14 +92,21 @@ endif() list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) -if (CMAKE_Fortran_COMPILER_ID STREQUAL "Intel") - include(Compiler-Intel) -elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") +if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") include(Compiler-GNU) + set(Fortran_COMPILER_VERSION_MIN 9.1) +elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel") + include(Compiler-Intel) + set(Fortran_COMPILER_VERSION_MIN 19) elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM") include(Compiler-IntelLLVM) + set(Fortran_COMPILER_VERSION_MIN 19) else() - message(FATAL_ERROR "Compiler type(CMAKE_Fortran_COMPILER_ID) not recognized") + message(FATAL_ERROR "Compiler '${CMAKE_Fortran_COMPILER_ID}' not supported") +endif() + +if(CMAKE_Fortran_COMPILER_VERSION VERSION_LESS Fortran_COMPILER_VERSION_MIN) + message(FATAL_ERROR "Version '${CMAKE_Fortran_COMPILER_VERSION}' of '${CMAKE_Fortran_COMPILER_ID}' is not supported") endif() file(STRINGS "$ENV{PETSC_DIR}/$ENV{PETSC_ARCH}/lib/petsc/conf/petscvariables" PETSC_EXTERNAL_LIB REGEX "PETSC_EXTERNAL_LIB_BASIC = .*$?") diff --git a/Makefile b/Makefile index d5ba1bdad..0017b4a97 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,11 @@ mesh: @cmake -B build/mesh -DDAMASK_SOLVER=mesh -DCMAKE_INSTALL_PREFIX=${PWD} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILDCMD_POST=${BUILDCMD_POST} -DBUILDCMD_PRE=${BUILDCMD_PRE} -DOPTIMIZATION=${OPTIMIZATION} -DOPENMP=${OPENMP} @cmake --build build/mesh --parallel --target install +.PHONY: test +test: + @cmake -B build/test -DDAMASK_SOLVER=test -DCMAKE_INSTALL_PREFIX=${PWD} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILDCMD_POST=${BUILDCMD_POST} -DBUILDCMD_PRE=${BUILDCMD_PRE} -DOPTIMIZATION=${OPTIMIZATION} -DOPENMP=${OPENMP} + @cmake --build build/test --parallel --target install + .PHONY: clean clean: @rm -rf build diff --git a/PRIVATE b/PRIVATE index 547bfe56d..22a23a9d5 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 547bfe56d67cba358a7bb9582f2f7c0e344befd8 +Subproject commit 22a23a9d5939d49d9d277c7066d9b68003a33324 diff --git a/VERSION b/VERSION index 211a34cab..495329abd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0-alpha7-297-g22de899aa +3.0.0-alpha7-534-g51210a05e diff --git a/cmake/Compiler-Intel.cmake b/cmake/Compiler-Intel.cmake index 69aee45ae..d68eac50b 100644 --- a/cmake/Compiler-Intel.cmake +++ b/cmake/Compiler-Intel.cmake @@ -93,8 +93,6 @@ set (DEBUG_FLAGS "${DEBUG_FLAGS},pointers") # ... for certain disassociated or uninitialized pointers or unallocated allocatable objects. set (DEBUG_FLAGS "${DEBUG_FLAGS},uninit") # ... for uninitialized variables. -set (DEBUG_FLAGS "${DEBUG_FLAGS} -ftrapuv") -# ... initializes stack local variables to an unusual value to aid error detection set (DEBUG_FLAGS "${DEBUG_FLAGS} -fpe-all=0 -ftz") # ... capture all floating-point exceptions, need to overwrite -no-ftz diff --git a/cmake/Compiler-IntelLLVM.cmake b/cmake/Compiler-IntelLLVM.cmake index c6e6208b6..f2fb8bce9 100644 --- a/cmake/Compiler-IntelLLVM.cmake +++ b/cmake/Compiler-IntelLLVM.cmake @@ -6,7 +6,7 @@ if (CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 18.0) endif () if (OPENMP) - set (OPENMP_FLAGS "-qopenmp") + set (OPENMP_FLAGS "-fiopenmp") endif () if (OPTIMIZATION STREQUAL "OFF" OR OPTIMIZATION STREQUAL "DEBUG") @@ -23,6 +23,8 @@ endif () set (STANDARD_CHECK "-stand f18 -assume nostd_mod_proc_name") set (LINKER_FLAGS "${LINKER_FLAGS} -shared-intel") # Link against shared Intel libraries instead of static ones +set (LINKER_FLAGS "${LINKER_FLAGS} -shared-intel -fc=ifx") +# enforce use of ifx for MPI wrapper #------------------------------------------------------------------------------------------------ # Fine tuning compilation options @@ -93,8 +95,6 @@ set (DEBUG_FLAGS "${DEBUG_FLAGS},pointers") # ... for certain disassociated or uninitialized pointers or unallocated allocatable objects. set (DEBUG_FLAGS "${DEBUG_FLAGS},uninit") # ... for uninitialized variables. -set (DEBUG_FLAGS "${DEBUG_FLAGS} -ftrapuv") -# ... initializes stack local variables to an unusual value to aid error detection set (DEBUG_FLAGS "${DEBUG_FLAGS} -fpe-all=0 -ftz") # ... capture all floating-point exceptions, need to overwrite -no-ftz diff --git a/examples/config/debug.yaml b/examples/config/debug.yaml deleted file mode 100644 index fef3cedeb..000000000 --- a/examples/config/debug.yaml +++ /dev/null @@ -1,12 +0,0 @@ -phase: [basic, extensive, selective] -materialpoint: [basic, extensive, selective] - -# options for selective debugging -element: 1 -integrationpoint: 1 -constituent: 1 - -# solver-specific -mesh: [PETSc] -grid: [basic, rotation, PETSc] -Marc: [basic] diff --git a/examples/config/phase/damage/anisobrittle_cubic.yaml b/examples/config/phase/damage/anisobrittle_cubic.yaml index 4f8db50ee..a7986a190 100644 --- a/examples/config/phase/damage/anisobrittle_cubic.yaml +++ b/examples/config/phase/damage/anisobrittle_cubic.yaml @@ -6,8 +6,8 @@ N_cl: [3] g_crit: [0.5e+7] s_crit: [0.006666] -dot_o: 1.e-3 -q: 20 +dot_o_0: 1.e-3 +p: 20 l_c: 1.0 mu: 0.001 diff --git a/examples/config/phase/mechanical/elastic/Hooke_Fe.yaml b/examples/config/phase/mechanical/elastic/Hooke_Fe.yaml index e307e94d3..983684d6e 100644 --- a/examples/config/phase/mechanical/elastic/Hooke_Fe.yaml +++ b/examples/config/phase/mechanical/elastic/Hooke_Fe.yaml @@ -3,7 +3,7 @@ type: Hooke references: - D.J. Dever, Journal of Applied Physics 43(8):3293-3301, 1972, - https://doi.org/10.1063/1.1661710 + https://doi.org/10.1063/1.1661710, fit to Tab. II (T_min=25ºC, T_max=880ºC) C_11: 232.2e+9 diff --git a/examples/config/phase/mechanical/elastic/Hooke_IN625.yaml b/examples/config/phase/mechanical/elastic/Hooke_IN625.yaml index fefd0389b..dd0d0566f 100644 --- a/examples/config/phase/mechanical/elastic/Hooke_IN625.yaml +++ b/examples/config/phase/mechanical/elastic/Hooke_IN625.yaml @@ -1,7 +1,7 @@ type: Hooke references: - - Wang et al., + - Z. Wang et al., Materials Science and Engineering:A 674:406-412, 2016, https://doi.org/10.1016/j.msea.2016.08.010, fit to Tab. 2 (last 3 rows) diff --git a/examples/config/phase/mechanical/elastic/Hooke_SAE1050-martensite.yaml b/examples/config/phase/mechanical/elastic/Hooke_SAE1050-martensite.yaml index 191756cc7..ea11f8618 100644 --- a/examples/config/phase/mechanical/elastic/Hooke_SAE1050-martensite.yaml +++ b/examples/config/phase/mechanical/elastic/Hooke_SAE1050-martensite.yaml @@ -3,8 +3,9 @@ type: Hooke references: - S.A. Kim and W.L. Johnson, Materials Science & Engineering A 452-453:633-639, 2007, - https://doi.org/10.1016/j.msea.2006.11.147 + https://doi.org/10.1016/j.msea.2006.11.147, + Tab. 1 (averaged for bcc) -C_11: 268.1e+9 -C_12: 111.2e+9 -C_44: 79.06e+9 +C_11: 267.9e+9 +C_12: 110.8e+9 +C_44: 78.9e+9 diff --git a/examples/config/phase/mechanical/plastic/dislotungsten_W.yaml b/examples/config/phase/mechanical/plastic/dislotungsten_W.yaml index 7c7a04c58..42aebec22 100644 --- a/examples/config/phase/mechanical/plastic/dislotungsten_W.yaml +++ b/examples/config/phase/mechanical/plastic/dislotungsten_W.yaml @@ -3,7 +3,7 @@ type: dislotungsten references: - D. Cereceda et al., International Journal of Plasticity 78:242-265, 2016, - http://dx.doi.org/10.1016/j.ijplas.2015.09.002 + https://doi.org/10.1016/j.ijplas.2015.09.002 - R. Gröger et al., Acta Materialia 56(19):5412-5425, 2008, https://doi.org/10.1016/j.actamat.2008.07.037 diff --git a/examples/config/phase/mechanical/plastic/kinehardening_317L.yaml b/examples/config/phase/mechanical/plastic/kinehardening_317L.yaml new file mode 100644 index 000000000..423b504b4 --- /dev/null +++ b/examples/config/phase/mechanical/plastic/kinehardening_317L.yaml @@ -0,0 +1,23 @@ +type: kinehardening + +references: + - J.A. Wollmershauser et al., + International Journal of Fatigue 36(1):181-193, 2012, + https://doi.org/10.1016/j.ijfatigue.2011.07.008 + +output: [xi, chi, chi_flip, gamma_flip, gamma, sgn(gamma)] + +N_sl: [12] + +xi_0: [0.070e+9] # τ_0,for +xi_inf: [0.015e+9] # τ_1,for +h_0_xi: [0.065e+9] # θ_0,for +h_inf_xi: [0.045e+9] # θ_1,for + +chi_inf: [0.027e+9] # τ_1,bs +h_0_chi: [55e+9] # θ_0,bs +h_inf_chi: [1.3e+9] # θ_1,bs + +n: 20 # not mentioned in the reference +dot_gamma_0: 1e-4 # not mentioned in the reference +h_sl-sl: [1, 1, 1, 1, 1, 1, 1] diff --git a/examples/config/phase/mechanical/plastic/phenopowerlaw_AA6022-T4.yaml b/examples/config/phase/mechanical/plastic/phenopowerlaw_AA6022-T4.yaml new file mode 100644 index 000000000..36e1a1cc8 --- /dev/null +++ b/examples/config/phase/mechanical/plastic/phenopowerlaw_AA6022-T4.yaml @@ -0,0 +1,19 @@ +type: phenopowerlaw + +references: + - T.J. Barrett and M. Knezevic, + Computer Methods in Applied Mechanics and Engineering 354:245-270, 2019, + https://doi.org/10.1016/j.cma.2019.05.035, + fitted to data shown in Fig 1 and Fig. 2a + +output: [xi_sl, gamma_sl] + +N_sl: [12] + +n_sl: 20 +a_sl: 3.7 +h_0_sl-sl: 1.02e+9 +xi_0_sl: [76.e+6] +xi_inf_sl: [266.e+6] +h_sl-sl: [1, 1, 5.123, 0.574, 1.123, 1.123, 1] +dot_gamma_0_sl: 0.001 diff --git a/examples/config/phase/mechanical/plastic/phenopowerlaw_Al.yaml b/examples/config/phase/mechanical/plastic/phenopowerlaw_Al.yaml index 68c51cdea..76194d700 100644 --- a/examples/config/phase/mechanical/plastic/phenopowerlaw_Al.yaml +++ b/examples/config/phase/mechanical/plastic/phenopowerlaw_Al.yaml @@ -4,19 +4,16 @@ references: - W.F. Hosford et al., Acta Metallurgica 8(3):187-199, 1960, https://doi.org/10.1016/0001-6160(60)90127-9, - fitted from Fig. 5 - - U.F. Kocks, - Metallurgical and Materials Transactions B 1:1121–1143, 1970, - https://doi.org/10.1007/BF02900224 + fitted to Fig. 5 ([111] and [001]) output: [xi_sl, gamma_sl] N_sl: [12] n_sl: 20 -a_sl: 3.1 -h_0_sl-sl: 1.7e+8 -xi_0_sl: [5.0e+6] -xi_inf_sl: [37.5e+6] -h_sl-sl: [1, 1, 1.4, 1.4, 1.4, 1.4, 1.4] +a_sl: 5.4 +h_0_sl-sl: 281.5e+6 +xi_0_sl: [2.69e+6] +xi_inf_sl: [67.5e+6] +h_sl-sl: [1, 1, 5.123, 0.574, 1.123, 1.123, 1] dot_gamma_0_sl: 7.5e-5 diff --git a/examples/config/phase/mechanical/plastic/phenopowerlaw_Cu.yaml b/examples/config/phase/mechanical/plastic/phenopowerlaw_Cu.yaml index 223495d26..08f366b15 100644 --- a/examples/config/phase/mechanical/plastic/phenopowerlaw_Cu.yaml +++ b/examples/config/phase/mechanical/plastic/phenopowerlaw_Cu.yaml @@ -1,22 +1,19 @@ type: phenopowerlaw references: - - T Takeuchi, + - T. Takeuchi, Transactions of the Japan Institute of Metals 16(10):629-640, 1975, https://doi.org/10.2320/matertrans1960.16.629, - fitted from Fig. 3b - - U.F. Kocks, - Metallurgical and Materials Transactions B 1:1121–1143, 1970, - https://doi.org/10.1007/BF02900224 + fitted to Fig. 3b ([111] and [001]) output: [xi_sl, gamma_sl] N_sl: [12] n_sl: 20 -a_sl: 1.0 -h_0_sl-sl: 2.4e+8 -xi_0_sl: [1.5e+6] -xi_inf_sl: [112.5e+6] -h_sl-sl: [1, 1, 1.4, 1.4, 1.4, 1.4, 1.4] +a_sl: 0.6 +h_0_sl-sl: 3.5e+8 +xi_0_sl: [1.6e+6] +xi_inf_sl: [96.4e+6] +h_sl-sl: [1, 1, 5.123, 0.574, 1.123, 1.123, 1] dot_gamma_0_sl: 3.e-3 diff --git a/examples/config/phase/mechanical/plastic/phenopowerlaw_Pt-5%Cu.yaml b/examples/config/phase/mechanical/plastic/phenopowerlaw_Pt-5%Cu.yaml index 864237825..59b58cdb1 100644 --- a/examples/config/phase/mechanical/plastic/phenopowerlaw_Pt-5%Cu.yaml +++ b/examples/config/phase/mechanical/plastic/phenopowerlaw_Pt-5%Cu.yaml @@ -4,17 +4,16 @@ references: - K.M. Jackson and C. Lang, Platinum Metals Review 50:15-19, 2006, https://doi.org/10.1595/147106705X93359, - fitted from Fig. 5 (Pt-5% Cu recrystallised) - - U.F. Kocks, - Metallurgical and Materials Transactions B 1:1121–1143, 1970, - https://doi.org/10.1007/BF02900224 + fitted to Fig. 5 (Pt-5% Cu recrystallised) + +output: [xi_sl, gamma_sl] N_sl: [12] -n_sl: 1.6 -a_sl: 0.8 -h_0_sl-sl: 300.0e+6 -xi_0_sl: [150.0e+6] -xi_inf_sl: [500.0e+6] -h_sl-sl: [1, 1, 1.4, 1.4, 1.4, 1.4, 1.4] -dot_gamma_0_sl: 0.0001 +n_sl: 20 +a_sl: 0.9 +h_0_sl-sl: 781.2e+6 +xi_0_sl: [114.e+6] +xi_inf_sl: [207.e+6] +h_sl-sl: [1, 1, 5.123, 0.574, 1.123, 1.123, 1] +dot_gamma_0_sl: 0.001 diff --git a/python/damask/__init__.py b/python/damask/__init__.py index aa3c36b07..fd49a00e4 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -25,5 +25,6 @@ from ._colormap import Colormap # noqa from ._vtk import VTK # noqa from ._config import Config # noqa from ._configmaterial import ConfigMaterial # noqa +from ._loadcasegrid import LoadcaseGrid # noqa from ._grid import Grid # noqa from ._result import Result # noqa diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 50ff910e6..ccb8d3d70 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -28,10 +28,10 @@ _REF_WHITE = np.array([.95047, 1.00000, 1.08883]) class Colormap(mpl.colors.ListedColormap): """ - Enhance matplotlib colormap functionality to be used within DAMASK. + Enhance matplotlib colormap functionality for use within DAMASK. Colors are internally stored as R(ed) G(green) B(lue) values. - The colormap can be used in matplotlib, seaborn, etc., or can + A colormap can be used in matplotlib, seaborn, etc., or can be exported to file for external use. References @@ -153,12 +153,12 @@ class Colormap(mpl.colors.ListedColormap): - 'hsl': Hue Saturation Luminance. - 'xyz': CIE Xyz. - 'lab': CIE Lab. - - 'msh': Msh (for perceptual uniform interpolation). + - 'msh': Msh (for perceptually uniform interpolation). Returns ------- new : damask.Colormap - Colormap within given bounds. + Colormap spanning given bounds. Examples -------- @@ -276,7 +276,7 @@ class Colormap(mpl.colors.ListedColormap): def shade(self, field: np.ndarray, bounds: Optional[FloatSequence] = None, - gap: Optional[float] = None) -> Image: + gap: Optional[float] = None) -> Image.Image: """ Generate PIL image of 2D field using colormap. @@ -288,6 +288,7 @@ class Colormap(mpl.colors.ListedColormap): Value range (left,right) spanned by colormap. gap : field.dtype, optional Transparent value. NaN will always be rendered transparent. + Defaults to None. Returns ------- @@ -334,6 +335,7 @@ class Colormap(mpl.colors.ListedColormap): -------- >>> import damask >>> damask.Colormap.from_predefined('stress').reversed() + Colormap: stress_r """ rev = super().reversed(name) @@ -353,6 +355,7 @@ class Colormap(mpl.colors.ListedColormap): If None, colormap name + suffix. suffix: str, optional Extension to use for colormap file. + Defaults to empty. Returns ------- @@ -452,8 +455,8 @@ class Colormap(mpl.colors.ListedColormap): References ---------- - https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf - https://www.kennethmoreland.com/color-maps/diverging_map.py + | https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf + | https://www.kennethmoreland.com/color-maps/diverging_map.py """ def rad_diff(a,b): @@ -735,8 +738,8 @@ class Colormap(mpl.colors.ListedColormap): References ---------- - https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf - https://www.kennethmoreland.com/color-maps/diverging_map.py + | https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf + | https://www.kennethmoreland.com/color-maps/diverging_map.py """ M = np.linalg.norm(lab) @@ -763,8 +766,8 @@ class Colormap(mpl.colors.ListedColormap): References ---------- - https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf - https://www.kennethmoreland.com/color-maps/diverging_map.py + | https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf + | https://www.kennethmoreland.com/color-maps/diverging_map.py """ return np.array([ diff --git a/python/damask/_config.py b/python/damask/_config.py index 1be1e313a..25fcbfa75 100644 --- a/python/damask/_config.py +++ b/python/damask/_config.py @@ -2,6 +2,7 @@ import copy from io import StringIO from collections.abc import Iterable import abc +import platform from typing import Optional, Union, Dict, Any, Type, TypeVar import numpy as np @@ -43,7 +44,7 @@ class NiceDumper(SafeDumper): return self.represent_data(data.tolist()) if isinstance(data, Rotation): return self.represent_data(data.quaternion.tolist()) - if hasattr(data, 'dtype'): + if isinstance(data, np.generic): return self.represent_data(data.item()) return super().represent_data(data) @@ -57,15 +58,42 @@ class Config(dict): """YAML-based configuration.""" def __init__(self, - yml: Union[None, str, Dict[str, Any]] = None, + config: Optional[Union[str, Dict[str, Any]]] = None, **kwargs): - """Initialize from YAML, dict, or key=value pairs.""" - if isinstance(yml,str): - kwargs.update(yaml.load(yml, Loader=SafeLoader)) - elif isinstance(yml,dict): - kwargs.update(yml) + """ + New YAML-based configuration. + + Parameters + ---------- + config : dict or str, optional + Configuration. String needs to be valid YAML. + **kwargs: arbitray keyword-value pairs, optional + Top level entries of the configuration. + + Notes + ----- + Values given as keyword-value pairs take precedence + over entries with the same keyword in 'config'. + + """ + if int(platform.python_version_tuple()[1]) >= 9: + if isinstance(config,str): + kwargs = yaml.load(config, Loader=SafeLoader) | kwargs + elif isinstance(config,dict): + kwargs = config | kwargs # type: ignore + + super().__init__(**kwargs) + else: + if isinstance(config,str): + c = yaml.load(config, Loader=SafeLoader) + elif isinstance(config,dict): + c = config.copy() + else: + c = {} + c.update(kwargs) + + super().__init__(**c) - super().__init__(**kwargs) def __repr__(self) -> str: """ diff --git a/python/damask/_configmaterial.py b/python/damask/_configmaterial.py index 5ee8ea73d..2eba905a6 100644 --- a/python/damask/_configmaterial.py +++ b/python/damask/_configmaterial.py @@ -1,12 +1,14 @@ +from typing import Optional, Union, Sequence, Dict, Any, List + import numpy as np import h5py -from typing import Optional, Union, Sequence, Dict, Any, Collection -from ._typehints import FileHandle +from ._typehints import FileHandle, FloatSequence, StrSequence from . import Config from . import Rotation from . import Orientation from . import util +from . import tensor from . import Table @@ -22,33 +24,43 @@ class ConfigMaterial(Config): """ def __init__(self, - d: Optional[Dict[str, Any]] = None, - **kwargs): + config: Optional[Union[str,Dict[str,Any]]] = None,*, + homogenization: Optional[Dict[str,Dict]] = None, + phase: Optional[Dict[str,Dict]] = None, + material: Optional[List[Dict[str,Any]]] = None): """ New material configuration. Parameters ---------- - d : dictionary or YAML string, optional - Initial content. Defaults to None, in which case empty entries for - any missing material, homogenization, and phase entry are created. - kwargs : key=value pairs, optional - Initial content specified as pairs of key=value. + config : dict or str, optional + Material configuration. String needs to be valid YAML. + homogenization : dict, optional + Homogenization configuration. + Defaults to an empty dict if 'config' is not given. + phase : dict, optional + Phase configuration. + Defaults to an empty dict if 'config' is not given. + material : dict, optional + Materialpoint configuration. + Defaults to an empty list if 'config' is not given. """ - default: Collection - if d is None: - for section, default in {'material':[],'homogenization':{},'phase':{}}.items(): - if section not in kwargs: kwargs.update({section:default}) + kwargs: Dict[str,Union[Dict[str,Dict],List[Dict[str,Any]]]] = {} + for arg,value in zip(['homogenization','phase','material'],[homogenization,phase,material]): + if value is None and config is None: + kwargs[arg] = [] if arg == 'material' else {} + elif value is not None: + kwargs[arg] = value - super().__init__(d,**kwargs) + super().__init__(config,**kwargs) def save(self, fname: FileHandle = 'material.yaml', **kwargs): """ - Save to yaml file. + Save to YAML file. Parameters ---------- @@ -65,7 +77,7 @@ class ConfigMaterial(Config): def load(cls, fname: FileHandle = 'material.yaml') -> 'ConfigMaterial': """ - Load from yaml file. + Load from YAML file. Parameters ---------- @@ -168,8 +180,12 @@ class ConfigMaterial(Config): @staticmethod - def from_table(table: Table, - **kwargs) -> 'ConfigMaterial': + def from_table(table: Table,*, + homogenization: Optional[Union[str,StrSequence]] = None, + phase: Optional[Union[str,StrSequence]] = None, + v: Optional[Union[str,FloatSequence]] = None, + O: Optional[Union[str,FloatSequence]] = None, + V_e: Optional[Union[str,FloatSequence]] = None) -> 'ConfigMaterial': """ Generate from an ASCII table. @@ -177,16 +193,33 @@ class ConfigMaterial(Config): ---------- table : damask.Table Table that contains material information. - **kwargs - Keyword arguments where the key is the property name and - the value specifies either the label of the data column in the table - or a constant value. + homogenization: (array-like) of str, optional + Homogenization label. + phase: (array-like) of str, optional + Phase label (per constituent). + v: (array-like) of float or str, optional + Constituent volume fraction (per constituent). + Defaults to 1/N_constituent. + O: (array-like) of damask.Rotation or np.array/list of shape(4) or str, optional + Orientation as unit quaternion (per constituent). + V_e: (array-like) of np.array/list of shape(3,3) or str, optional + Left elastic stretch (per constituent). + Returns ------- new : damask.ConfigMaterial Material configuration from values in table. + Notes + ----- + If the value of an argument is a string that is a column label, + data from the table is used to fill the corresponding entry in + the material configuration. Otherwise, the value is used directly. + + First index of array-like values that are defined per constituent + runs over materials, whereas second index runs over constituents. + Examples -------- >>> import damask @@ -228,15 +261,16 @@ class ConfigMaterial(Config): phase: {Aluminum: null, Steel: null} """ - kwargs_ = {k:table.get(v) if v in table.labels else np.atleast_2d([v]*len(table)).T for k,v in kwargs.items()} + kwargs = {} + for arg,val in zip(['homogenization','phase','v','O','V_e'],[homogenization,phase,v,O,V_e]): + if val is not None: + kwargs[arg] = table.get(val) if val in table.labels else np.atleast_2d([val]*len(table)).T # type: ignore - _,idx = np.unique(np.hstack(list(kwargs_.values())),return_index=True,axis=0) + _,idx = np.unique(np.hstack(list(kwargs.values())),return_index=True,axis=0) idx = np.sort(idx) - kwargs_ = {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs_.items()} - for what in ['phase','homogenization']: - if what not in kwargs_: kwargs_[what] = what+'_label' + kwargs = {k:np.atleast_1d(v[idx].squeeze()) for k,v in kwargs.items()} - return ConfigMaterial().material_add(**kwargs_) + return ConfigMaterial().material_add(**kwargs) @property @@ -361,7 +395,7 @@ class ConfigMaterial(Config): Parameters ---------- - mapping: dictionary + mapping: dict Mapping from old name to new name ID: list of ints, optional Limit renaming to selected material IDs. @@ -394,7 +428,7 @@ class ConfigMaterial(Config): Parameters ---------- - mapping: dictionary + mapping: dict Mapping from old name to new name ID: list of ints, optional Limit renaming to selected homogenization IDs. @@ -416,11 +450,11 @@ class ConfigMaterial(Config): def material_add(self,*, - homogenization: Any = None, - phase: Any = None, - v: Any = None, - O: Any = None, - V_e: Any = None) -> 'ConfigMaterial': + homogenization: Optional[Union[str,StrSequence]] = None, + phase: Optional[Union[str,StrSequence]] = None, + v: Optional[Union[float,FloatSequence]] = None, + O: Optional[Union[float,FloatSequence]] = None, + V_e: Optional[Union[float,FloatSequence]] = None) -> 'ConfigMaterial': """ Add material entries. @@ -432,6 +466,7 @@ class ConfigMaterial(Config): Phase label (per constituent). v: (array-like) of float, optional Constituent volume fraction (per constituent). + Defaults to 1/N_constituent. O: (array-like) of damask.Rotation or np.array/list of shape(4), optional Orientation as unit quaternion (per constituent). V_e: (array-like) of np.array/list of shape(3,3), optional @@ -444,9 +479,8 @@ class ConfigMaterial(Config): Notes ----- - First index of array-like values that are defined per - consituent runs over materials, whereas second index runs - over constituents. + First index of array-like values that are defined per constituent + runs over materials, whereas second index runs over constituents. Examples -------- @@ -525,49 +559,48 @@ class ConfigMaterial(Config): phase: {Austenite: null, Ferrite: null} """ - kwargs = {} - for keyword,value in zip(['homogenization','phase','v','O','V_e'],[homogenization,phase,v,O,V_e]): - if value is not None: kwargs[keyword] = value + dim = {'O':(4,),'V_e':(3,3,)} + ex = dict((keyword, -len(val)) for keyword,val in dim.items()) - _constituent_properties = ['phase','O','v','V_e'] - _dim = {'O':(4,),'V_e':(3,3,)} - _ex = dict((k, -len(v)) for k, v in _dim.items()) + N_materials,N_constituents = 1,1 + shape = {} + for arg,val in zip(['homogenization','phase','v','O','V_e'],[homogenization,phase,v,O,V_e]): + if val is None: continue + shape[arg] = np.array(val) + s = shape[arg].shape[:ex.get(arg,None)] # type: ignore + N_materials = max(N_materials,s[0]) if len(s)>0 else N_materials + N_constituents = max(N_constituents,s[1]) if len(s)>1 else N_constituents - N,n = 1,1 - shaped : Dict[str, Union[None,np.ndarray]] = \ - {'v': None, - 'phase': None, - 'homogenization': None, - } + shape['v'] = np.array(shape.get('v',1./N_constituents),float) - for k,v in kwargs.items(): - shaped[k] = np.array(v) - s = shaped[k].shape[:_ex.get(k,None)] # type: ignore - N = max(N,s[0]) if len(s)>0 else N - n = max(n,s[1]) if len(s)>1 else n + mat: Sequence[dict] = [{'constituents':[{} for _ in range(N_constituents)]} for _ in range(N_materials)] - shaped['v'] = np.array(1./n) if shaped['v'] is None else shaped['v'] - - mat: Sequence[dict] = [{'constituents':[{} for _ in range(n)]} for _ in range(N)] - - for k,v in shaped.items(): - target = (N,n) + _dim.get(k,()) - obj = np.broadcast_to(np.array(v).reshape(util.shapeshifter(() if v is None else v.shape, - target, - mode = 'right')), - target) - for i in range(N): - if k in _constituent_properties: - for j in range(n): - mat[i]['constituents'][j][k] = obj[i,j].item() if isinstance(obj[i,j],np.generic) else obj[i,j] + for k,v in shape.items(): + target = (N_materials,N_constituents) + dim.get(k,()) + broadcasted = np.broadcast_to(np.array(v).reshape(util.shapeshifter(np.array(v).shape,target,'right')),target) + if k == 'v': + if np.min(broadcasted) < 0 or np.max(broadcasted) > 1: + raise ValueError('volume fraction "v" out of range') + if len(np.atleast_1d(broadcasted)) > 1: + total = np.sum(broadcasted,axis=-1) + if np.min(total) < 0 or np.max(total) > 1: + raise ValueError('volume fraction "v" out of range') + if k == 'O' and not np.allclose(1.0,np.linalg.norm(broadcasted,axis=-1)): + raise ValueError('orientation "O" is not a unit quaterion') + elif k == 'V_e' and not np.allclose(broadcasted,tensor.symmetric(broadcasted)): + raise ValueError('elastic stretch "V_e" is not symmetric') + for i in range(N_materials): + if k == 'homogenization': + mat[i][k] = broadcasted[i,0] else: - mat[i][k] = obj[i,0].item() if isinstance(obj[i,0],np.generic) else obj[i,0] + for j in range(N_constituents): + mat[i]['constituents'][j][k] = broadcasted[i,j] dup = self.copy() dup['material'] = dup['material'] + mat if 'material' in dup else mat - for what in [item for item in ['phase','homogenization'] if shaped[item] is not None]: - for k in np.unique(shaped[what]): # type: ignore + for what in [item for item in ['phase','homogenization'] if item in shape]: + for k in np.unique(shape[what]): # type: ignore if k not in dup[what]: dup[what][str(k)] = None return dup diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index ed694fb12..9434515f5 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -307,15 +307,13 @@ class Crystal(): Cubic crystal family: >>> import damask - >>> cubic = damask.Crystal(family='cubic') - >>> cubic + >>> (cubic := damask.Crystal(family='cubic')) Crystal family: cubic Body-centered cubic Bravais lattice with parameters of iron: >>> import damask - >>> Fe = damask.Crystal(lattice='cI', a=287e-12) - >>> Fe + >>> (Fe := damask.Crystal(lattice='cI', a=287e-12)) Crystal family: cubic Bravais lattice: cI a=2.87e-10 m, b=2.87e-10 m, c=2.87e-10 m @@ -406,7 +404,7 @@ class Crystal(): """ Return repr(self). - Give short human-readable summary. + Give short, human-readable summary. """ family = f'Crystal family: {self.family}' diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 5f58a9c75..a0571279c 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -32,10 +32,10 @@ class Grid: """ Geometry definition for grid solvers. - Create and manipulate geometry definitions for storage as VTK - image data files ('.vti' extension). A grid contains the - material ID (referring to the entry in 'material.yaml') and - the physical size. + Create and manipulate geometry definitions for storage as VTK ImageData + files ('.vti' extension). A grid has a physical size, a coordinate origin, + and contains the material ID (indexing an entry in 'material.yaml') + as well as initial condition fields. """ def __init__(self, @@ -57,7 +57,7 @@ class Grid: origin : sequence of float, len (3), optional Coordinates of grid origin in meter. Defaults to [0.0,0.0,0.0]. initial_conditions : dictionary, optional - Labels and values of the inital conditions at each material point. + Initial condition label and field values at each grid point. comments : (sequence of) str, optional Additional, human-readable information, e.g. history of operations. @@ -74,7 +74,7 @@ class Grid: """ Return repr(self). - Give short human-readable summary. + Give short, human-readable summary. """ mat_min = np.nanmin(self.material) @@ -144,7 +144,7 @@ class Grid: @property def size(self) -> np.ndarray: - """Physical size of grid in meter.""" + """Edge lengths of grid in meter.""" return self._size @size.setter @@ -157,7 +157,7 @@ class Grid: @property def origin(self) -> np.ndarray: - """Coordinates of grid origin in meter.""" + """Vector to grid origin in meter.""" return self._origin @origin.setter @@ -186,7 +186,7 @@ class Grid: @property def cells(self) -> np.ndarray: - """Number of cells in x,y,z direction.""" + """Cell counts along x,y,z direction.""" return np.asarray(self.material.shape) @@ -199,7 +199,7 @@ class Grid: @staticmethod def load(fname: Union[str, Path]) -> 'Grid': """ - Load from VTK image data file. + Load from VTK ImageData file. Parameters ---------- @@ -317,6 +317,11 @@ class Grid: loaded : damask.Grid Grid-based geometry from file. + Notes + ----- + Material indices in Neper usually start at 1 unless + a buffer material with index 0 is added. + Examples -------- Read a periodic polycrystal generated with Neper. @@ -325,7 +330,7 @@ class Grid: >>> N_grains = 20 >>> cells = (32,32,32) >>> damask.util.run(f'neper -T -n {N_grains} -tesrsize {cells[0]}:{cells[1]}:{cells[2]} -periodicity all -format vtk') - >>> damask.Grid.load_Neper(f'n{N_grains}-id1.vtk') + >>> damask.Grid.load_Neper(f'n{N_grains}-id1.vtk').renumber() cells: 32 × 32 × 32 size: 1.0 × 1.0 × 1.0 m³ origin: 0.0 0.0 0.0 m @@ -336,7 +341,7 @@ class Grid: cells = np.array(v.vtk_data.GetDimensions())-1 bbox = np.array(v.vtk_data.GetBounds()).reshape(3,2).T - return Grid(material = v.get('MaterialId').reshape(cells,order='F').astype('int32',casting='unsafe') - 1, + return Grid(material = v.get('MaterialId').reshape(cells,order='F').astype('int32',casting='unsafe'), size = bbox[1] - bbox[0], origin = bbox[0], comments = util.execution_stamp('Grid','load_Neper'), @@ -470,9 +475,9 @@ class Grid: Parameters ---------- cells : sequence of int, len (3) - Number of cells in x,y,z direction. + Cell counts along x,y,z direction. size : sequence of float, len (3) - Physical size of the grid in meter. + Edge lengths of the grid in meter. seeds : numpy.ndarray of float, shape (:,3) Position of the seed points in meter. All points need to lay within the box. weights : sequence of float, len (seeds.shape[0]) @@ -527,9 +532,9 @@ class Grid: Parameters ---------- cells : sequence of int, len (3) - Number of cells in x,y,z direction. + Cell counts along x,y,z direction. size : sequence of float, len (3) - Physical size of the grid in meter. + Edge lengths of the grid in meter. seeds : numpy.ndarray of float, shape (:,3) Position of the seed points in meter. All points need to lay within the box. material : sequence of int, len (seeds.shape[0]), optional @@ -608,14 +613,14 @@ class Grid: periods: int = 1, materials: IntSequence = (0,1)) -> 'Grid': """ - Create grid from definition of triply periodic minimal surface. + Create grid from definition of triply-periodic minimal surface. Parameters ---------- cells : sequence of int, len (3) - Number of cells in x,y,z direction. + Cell counts along x,y,z direction. size : sequence of float, len (3) - Physical size of the grid in meter. + Edge lengths of the grid in meter. surface : str Type of the minimal surface. See notes for details. threshold : float, optional. @@ -664,19 +669,19 @@ class Grid: >>> import numpy as np >>> import damask >>> damask.Grid.from_minimal_surface([64]*3,np.ones(3)*1.e-4,'Gyroid') - cells : 64 x 64 x 64 - size : 0.0001 x 0.0001 x 0.0001 m³ + cells : 64 × 64 × 64 + size : 0.0001 × 0.0001 × 0.0001 m³ origin: 0.0 0.0 0.0 m # materials: 2 - Minimal surface of 'Neovius' type with non-default material IDs. + Minimal surface of 'Neovius' type with specific material IDs. >>> import numpy as np >>> import damask >>> damask.Grid.from_minimal_surface([80]*3,np.ones(3)*5.e-4, ... 'Neovius',materials=(1,5)) - cells : 80 x 80 x 80 - size : 0.0005 x 0.0005 x 0.0005 m³ + cells : 80 × 80 × 80 + size : 0.0005 × 0.0005 × 0.0005 m³ origin: 0.0 0.0 0.0 m # materials: 2 (min: 1, max: 5) @@ -695,12 +700,13 @@ class Grid: fname: Union[str, Path], compress: bool = True): """ - Save as VTK image data file. + Save as VTK ImageData file. Parameters ---------- fname : str or pathlib.Path - Filename to write. Valid extension is .vti, it will be appended if not given. + Filename to write. + Valid extension is .vti, which will be appended if not given. compress : bool, optional Compress with zlib algorithm. Defaults to True. @@ -727,7 +733,7 @@ class Grid: fname : str or file handle Geometry file to write with extension '.geom'. compress : bool, optional - Compress geometry with 'x of y' and 'a to b'. + Compress geometry using 'x of y' and 'a to b'. """ warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.0.0', DeprecationWarning,2) @@ -771,13 +777,13 @@ class Grid: Parameters ---------- cells : sequence of int, len (3), optional - Number of cells x,y,z direction. + Cell counts along x,y,z direction. offset : sequence of int, len (3), optional Offset (measured in cells) from old to new grid. Defaults to [0,0,0]. fill : int, optional Material ID to fill the background. - Defaults to material.max() + 1. + Defaults to material.max()+1. Returns ------- @@ -790,11 +796,11 @@ class Grid: >>> import numpy as np >>> import damask - >>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4) + >>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-3) >>> g.canvas([32,32,16],[0,0,16]) - cells : 33 x 32 x 16 - size : 0.0001 x 0.0001 x 5e-05 m³ - origin: 0.0 0.0 5e-05 m + cells: 32 × 32 × 16 + size: 0.001 × 0.001 × 0.0005 m³ + origin: 0.0 0.0 0.0005 m # materials: 1 """ @@ -837,16 +843,33 @@ class Grid: Examples -------- - Mirror along x- and y-direction. + Mirror along y-direction. >>> import numpy as np >>> import damask - >>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4) - >>> g.mirror('xy',True) - cells : 64 x 64 x 32 - size : 0.0002 x 0.0002 x 0.0001 m³ + >>> (g := damask.Grid(np.arange(4*5*6).reshape([4,5,6]),np.ones(3))) + cells: 4 × 5 × 6 + size: 1.0 × 1.0 × 1.0 m³ origin: 0.0 0.0 0.0 m - # materials: 1 + # materials: 120 + >>> g.mirror('y') + cells: 4 × 8 × 6 + size: 1.0 × 1.6 × 1.0 m³ + origin: 0.0 0.0 0.0 m + # materials: 120 + + Reflect along x- and y-direction. + + >>> g.mirror('xy',reflect=True) + cells: 8 × 10 × 6 + size: 2.0 × 2.0 × 1.0 m³ + origin: 0.0 0.0 0.0 m + # materials: 120 + + Independence of mirroring order. + + >>> g.mirror('xy') == g.mirror(['y','x']) + True """ if not set(directions).issubset(valid := ['x', 'y', 'z']): @@ -884,11 +907,29 @@ class Grid: updated : damask.Grid Updated grid-based geometry. + Examples + -------- + Invariance of flipping order. + + >>> import numpy as np + >>> import damask + >>> (g := damask.Grid(np.arange(4*5*6).reshape([4,5,6]),np.ones(3))) + cells: 4 × 5 × 6 + size: 1.0 × 1.0 × 1.0 m³ + origin: 0.0 0.0 0.0 m + # materials: 120 + >>> g.flip('xyz') == g.flip(['x','z','y']) + True + + Invariance of flipping a (fully) mirrored grid. + + >>> g.mirror('x',True) == g.mirror('x',True).flip('x') + True + """ if not set(directions).issubset(valid := ['x', 'y', 'z']): raise ValueError(f'invalid direction "{set(directions).difference(valid)}" specified') - mat = np.flip(self.material, [valid.index(d) for d in directions if d in valid]) return Grid(material = mat, @@ -902,7 +943,7 @@ class Grid: R: Rotation, fill: Optional[int] = None) -> 'Grid': """ - Rotate grid (and pad if required). + Rotate grid (possibly extending its bounding box). Parameters ---------- @@ -910,13 +951,27 @@ class Grid: Rotation to apply to the grid. fill : int, optional Material ID to fill enlarged bounding box. - Defaults to material.max() + 1. + Defaults to material.max()+1. Returns ------- updated : damask.Grid Updated grid-based geometry. + Examples + -------- + Rotation by 180° (π) is equivalent to twice flipping. + + >>> import numpy as np + >>> import damask + >>> (g := damask.Grid(np.arange(4*5*6).reshape([4,5,6]),np.ones(3))) + cells: 4 × 5 × 6 + size: 1.0 × 1.0 × 1.0 m³ + origin: 0.0 0.0 0.0 m + # materials: 120 + >>> g.rotate(damask.Rotation.from_axis_angle([0,0,1,180],degrees=True)) == g.flip('xy') + True + """ material = self.material # These rotations are always applied in the reference coordinate system, i.e. (z,x,z) not (z,x',z'') @@ -941,12 +996,12 @@ class Grid: def scale(self, cells: IntSequence) -> 'Grid': """ - Scale grid to new cell count. + Scale grid to new cell counts. Parameters ---------- cells : sequence of int, len (3) - Number of cells in x,y,z direction. + Cell counts along x,y,z direction. Returns ------- @@ -955,7 +1010,7 @@ class Grid: Examples -------- - Double resolution. + Double grid resolution. >>> import numpy as np >>> import damask @@ -965,8 +1020,8 @@ class Grid: origin: 0.0 0.0 0.0 m # materials: 1 >>> g.scale(g.cells*2) - cells : 64 x 64 x 64 - size : 0.0001 x 0.0001 x 0.0001 m³ + cells : 64 × 64 × 64 + size : 0.0001 × 0.0001 × 0.0001 m³ origin: 0.0 0.0 0.0 m # materials: 1 @@ -994,7 +1049,7 @@ class Grid: Parameters ---------- idx : numpy.ndarray of int, shape (:,:,:) or (:,:,:,3) - Grid of flat indices or coordinate indices. + Grid of flat indices or coordinate indices. Returns ------- @@ -1069,7 +1124,7 @@ class Grid: def sort(self) -> 'Grid': """ - Sort material indices such that min(material) is located at (0,0,0). + Sort material indices such that min(material ID) is located at (0,0,0). Returns ------- @@ -1186,7 +1241,7 @@ class Grid: fill : int, optional Fill value for primitive. Defaults to material.max()+1. R : damask.Rotation, optional - Rotation of primitive. Defaults to no rotation. + Rotation of the primitive. Defaults to no rotation. inverse : bool, optional Retain original materials within primitive and fill outside. Defaults to False. @@ -1206,8 +1261,8 @@ class Grid: >>> import damask >>> g = damask.Grid(np.zeros([64]*3,int), np.ones(3)*1e-4) >>> g.add_primitive(np.ones(3)*5e-5,np.ones(3)*5e-5,1) - cells : 64 x 64 x 64 - size : 0.0001 x 0.0001 x 0.0001 m³ + cells : 64 × 64 × 64 + size : 0.0001 × 0.0001 × 0.0001 m³ origin: 0.0 0.0 0.0 m # materials: 2 @@ -1217,8 +1272,8 @@ class Grid: >>> import damask >>> g = damask.Grid(np.zeros([64]*3,int), np.ones(3)*1e-4) >>> g.add_primitive(np.ones(3,int)*32,np.zeros(3),np.inf) - cells : 64 x 64 x 64 - size : 0.0001 x 0.0001 x 0.0001 m³ + cells : 64 × 64 × 64 + size : 0.0001 × 0.0001 × 0.0001 m³ origin: 0.0 0.0 0.0 m # materials: 2 diff --git a/python/damask/_loadcasegrid.py b/python/damask/_loadcasegrid.py new file mode 100644 index 000000000..496824713 --- /dev/null +++ b/python/damask/_loadcasegrid.py @@ -0,0 +1,78 @@ +from typing import Optional, Union, Dict, Any, List + +from numpy import ma +import yaml + +from ._typehints import FileHandle +from ._config import NiceDumper +from . import util +from . import Config + + +class MaskedMatrixDumper(NiceDumper): + """Format masked matrices.""" + + def represent_data(self, data: Any): + return super().represent_data(data.astype(object).filled('x') if isinstance(data, ma.core.MaskedArray) else data) # type: ignore[attr-defined] + + +class LoadcaseGrid(Config): + """Load case for grid solver.""" + + def __init__(self, + config: Optional[Union[str,Dict[str,Any]]] = None, + *, + solver: Optional[Dict[str,str]] = None, + loadstep: Optional[List[Dict[str,Any]]] = None): + """ + New grid solver load case. + + Parameters + ---------- + config : dict or str, optional + Grid solver load case. String needs to be valid YAML. + solver : dict, optional + Solver configuration. + Defaults to an empty dict if 'config' is not given. + loadstep : list of dict, optional + Load step configuration. + Defaults to an empty list if 'config' is not given. + + """ + kwargs: Dict[str,Union[Dict[str,str],List[Dict[str,Any]]]] = {} + default: Union[List,Dict] + for arg,value,default in [('solver',solver,{}),('loadstep',loadstep,[])]: # type: ignore[assignment] + if value is not None: + kwargs[arg] = value + elif config is None: + kwargs[arg] = default + + super().__init__(config,**kwargs) + + + def save(self, + fname: FileHandle, + **kwargs): + """ + Save to YAML file. + + Parameters + ---------- + fname : file, str, or pathlib.Path + Filename or file to write. + **kwargs : dict + Keyword arguments parsed to yaml.dump. + + """ + for key,default in dict(width=256, + default_flow_style=None, + sort_keys=False).items(): + if key not in kwargs: + kwargs[key] = default + + fhandle = util.open_text(fname,'w') + try: + fhandle.write(yaml.dump(self,Dumper=MaskedMatrixDumper,**kwargs)) + except TypeError: # compatibility with old pyyaml + del kwargs['sort_keys'] + fhandle.write(yaml.dump(self,Dumper=MaskedMatrixDumper,**kwargs)) diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index 2206d5b2a..4db24bae5 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -1,6 +1,5 @@ -import inspect import copy -from typing import Optional, Union, Callable, Dict, Any, Tuple, TypeVar +from typing import Optional, Union, TypeVar import numpy as np @@ -10,31 +9,6 @@ from . import Crystal from . import util from . import tensor - -_parameter_doc = \ - """ - family : {'triclinic', 'monoclinic', 'orthorhombic', 'tetragonal', 'hexagonal', 'cubic'}, optional. - Name of the crystal family. - Family will be inferred if 'lattice' is given. - lattice : {'aP', 'mP', 'mS', 'oP', 'oS', 'oI', 'oF', 'tP', 'tI', 'hP', 'cP', 'cI', 'cF'}, optional. - Name of the Bravais lattice in Pearson notation. - a : float, optional - Length of lattice parameter 'a'. - b : float, optional - Length of lattice parameter 'b'. - c : float, optional - Length of lattice parameter 'c'. - alpha : float, optional - Angle between b and c lattice basis. - beta : float, optional - Angle between c and a lattice basis. - gamma : float, optional - Angle between a and b lattice basis. - degrees : bool, optional - Angles are given in degrees. Defaults to False. - - """ - MyType = TypeVar('MyType', bound='Orientation') class Orientation(Rotation,Crystal): @@ -94,7 +68,7 @@ class Orientation(Rotation,Crystal): """ - @util.extend_docstring(extra_parameters=_parameter_doc) + @util.extend_docstring(adopted_parameters=Crystal.__init__) def __init__(self, rotation: Union[FloatSequence, Rotation] = np.array([1.,0.,0.,0.]), *, @@ -108,7 +82,7 @@ class Orientation(Rotation,Crystal): Parameters ---------- - rotation : list, numpy.ndarray, Rotation, optional + rotation : list, numpy.ndarray, or Rotation, optional Unit quaternion in positive real hemisphere. Use .from_quaternion to perform a sanity check. Defaults to no rotation. @@ -123,7 +97,7 @@ class Orientation(Rotation,Crystal): """ Return repr(self). - Give short human-readable summary. + Give short, human-readable summary. """ return util.srepr([Crystal.__repr__(self), @@ -261,134 +235,91 @@ class Orientation(Rotation,Crystal): Compound rotation self*other, i.e. first other then self rotation. """ - if isinstance(other, (Orientation,Rotation)): - return self.copy(Rotation(self.quaternion)*Rotation(other.quaternion)) - else: + if not isinstance(other, (Orientation,Rotation)): raise TypeError('use "O@b", i.e. matmul, to apply Orientation "O" to object "b"') - - - @staticmethod - def _split_kwargs(kwargs: Dict[str, Any], - target: Callable) -> Tuple[Dict[str, Any], ...]: - """ - Separate keyword arguments in 'kwargs' targeted at 'target' from general keyword arguments of Orientation objects. - - Parameters - ---------- - kwargs : dictionary - Contains all **kwargs. - target: method - Function to scan for kwarg signature. - - Returns - ------- - rot_kwargs: dictionary - Valid keyword arguments of 'target' function of Rotation class. - ori_kwargs: dictionary - Valid keyword arguments of Orientation object. - - """ - kws: Tuple[Dict[str, Any], ...] = () - for t in (target,Orientation.__init__): - kws += ({key: kwargs[key] for key in set(inspect.signature(t).parameters) & set(kwargs)},) - - invalid_keys = set(kwargs)-(set(kws[0])|set(kws[1])) - if invalid_keys: - raise TypeError(f"{inspect.stack()[1][3]}() got an unexpected keyword argument '{invalid_keys.pop()}'") - - return kws + return self.copy(Rotation(self.quaternion)*Rotation(other.quaternion)) @classmethod @util.extend_docstring(Rotation.from_random, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_random, wrapped=__init__) def from_random(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_random) - return cls(rotation=Rotation.from_random(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_quaternion, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_quaternion, wrapped=__init__) def from_quaternion(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_quaternion) - return cls(rotation=Rotation.from_quaternion(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_Euler_angles, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_Euler_angles, wrapped=__init__) def from_Euler_angles(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Euler_angles) - return cls(rotation=Rotation.from_Euler_angles(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_axis_angle, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_axis_angle, wrapped=__init__) def from_axis_angle(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_axis_angle) - return cls(rotation=Rotation.from_axis_angle(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_basis, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_basis, wrapped=__init__) def from_basis(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_basis) - return cls(rotation=Rotation.from_basis(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_matrix, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_matrix, wrapped=__init__) def from_matrix(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_matrix) - return cls(rotation=Rotation.from_matrix(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_Rodrigues_vector, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_Rodrigues_vector, wrapped=__init__) def from_Rodrigues_vector(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Rodrigues_vector) - return cls(rotation=Rotation.from_Rodrigues_vector(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_homochoric, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_homochoric, wrapped=__init__) def from_homochoric(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_homochoric) - return cls(rotation=Rotation.from_homochoric(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_cubochoric, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_cubochoric, wrapped=__init__) def from_cubochoric(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_cubochoric) - return cls(rotation=Rotation.from_cubochoric(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_spherical_component, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_spherical_component, wrapped=__init__) def from_spherical_component(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_spherical_component) - return cls(rotation=Rotation.from_spherical_component(**kwargs_rot),**kwargs_ori) - + return cls(**kwargs) @classmethod @util.extend_docstring(Rotation.from_fiber_component, - extra_parameters=_parameter_doc) + adopted_parameters=Crystal.__init__) + @util.pass_on('rotation', Rotation.from_fiber_component, wrapped=__init__) def from_fiber_component(cls, **kwargs) -> 'Orientation': - kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_fiber_component) - return cls(rotation=Rotation.from_fiber_component(**kwargs_rot),**kwargs_ori) + return cls(**kwargs) @classmethod - @util.extend_docstring(extra_parameters=_parameter_doc) + @util.extend_docstring(adopted_parameters=Crystal.__init__) def from_directions(cls, uvw: FloatSequence, hkl: FloatSequence, @@ -467,24 +398,24 @@ class Orientation(Rotation,Crystal): if self.family == 'cubic': return (np.prod(np.sqrt(2)-1. >= rho_abs,axis=-1) * (1. >= np.sum(rho_abs,axis=-1))).astype(bool) - elif self.family == 'hexagonal': + if self.family == 'hexagonal': return (np.prod(1. >= rho_abs,axis=-1) * (2. >= np.sqrt(3)*rho_abs[...,0] + rho_abs[...,1]) * (2. >= np.sqrt(3)*rho_abs[...,1] + rho_abs[...,0]) * (2. >= np.sqrt(3) + rho_abs[...,2])).astype(bool) - elif self.family == 'tetragonal': + if self.family == 'tetragonal': return (np.prod(1. >= rho_abs[...,:2],axis=-1) * (np.sqrt(2) >= rho_abs[...,0] + rho_abs[...,1]) * (np.sqrt(2) >= rho_abs[...,2] + 1.)).astype(bool) - elif self.family == 'orthorhombic': + if self.family == 'orthorhombic': return (np.prod(1. >= rho_abs,axis=-1)).astype(bool) - elif self.family == 'monoclinic': + if self.family == 'monoclinic': return np.logical_or( 1. >= rho_abs[...,1], np.isnan(rho_abs[...,1])) - elif self.family == 'triclinic': + if self.family == 'triclinic': return np.ones(rho_abs.shape[:-1]).astype(bool) - else: - raise TypeError(f'unknown symmetry "{self.family}"') + + raise TypeError(f'unknown symmetry "{self.family}"') @property @@ -510,38 +441,40 @@ class Orientation(Rotation,Crystal): return ((rho[...,0] >= rho[...,1]) & (rho[...,1] >= rho[...,2]) & (rho[...,2] >= 0)).astype(bool) - elif self.family == 'hexagonal': + if self.family == 'hexagonal': return ((rho[...,0] >= rho[...,1]*np.sqrt(3)) & (rho[...,1] >= 0) & (rho[...,2] >= 0)).astype(bool) - elif self.family == 'tetragonal': + if self.family == 'tetragonal': return ((rho[...,0] >= rho[...,1]) & (rho[...,1] >= 0) & (rho[...,2] >= 0)).astype(bool) - elif self.family == 'orthorhombic': + if self.family == 'orthorhombic': return ((rho[...,0] >= 0) & (rho[...,1] >= 0) & (rho[...,2] >= 0)).astype(bool) - elif self.family == 'monoclinic': + if self.family == 'monoclinic': return ((rho[...,1] >= 0) & (rho[...,2] >= 0)).astype(bool) - else: - return np.ones_like(rho[...,0],dtype=bool) + + return np.ones_like(rho[...,0],dtype=bool) def disorientation(self, other: 'Orientation', return_operators: bool = False) -> object: """ - Calculate disorientation between myself and given other orientation. + Calculate disorientation between self and given other orientation. Parameters ---------- other : Orientation Orientation to calculate disorientation for. Shape of other blends with shape of own rotation array. - For example, shapes of (2,3) for own rotations and (3,2) for other's result in (2,3,2) disorientations. + For example, shapes of (2,3) for own rotations + and (3,2) for other's result in (2,3,2) disorientations. return_operators : bool, optional - Return index pair of symmetrically equivalent orientations that result in disorientation axis falling into FZ. + Return index pair of symmetrically equivalent orientations + that result in disorientation axis falling into FZ. Defaults to False. Returns @@ -578,8 +511,8 @@ class Orientation(Rotation,Crystal): >>> N = 10000 >>> a = damask.Orientation.from_random(shape=N,family='cubic') >>> b = damask.Orientation.from_random(shape=N,family='cubic') - >>> d = a.disorientation(b).as_axis_angle(degrees=True,pair=True)[1] - >>> plt.hist(d,25) + >>> n,omega = a.disorientation(b).as_axis_angle(degrees=True,pair=True) + >>> plt.hist(omega,25) >>> plt.show() """ @@ -626,6 +559,7 @@ class Orientation(Rotation,Crystal): ---------- weights : numpy.ndarray, shape (self.shape), optional Relative weights of orientations. + Defaults to equal weights. return_cloud : bool, optional Return the specific (symmetrically equivalent) orientations that were averaged. Defaults to False. @@ -895,8 +829,8 @@ class Orientation(Rotation,Crystal): Schmid matrix (in lab frame) of first octahedral slip system of a face-centered cubic crystal in "Goss" orientation. - >>> import damask >>> import numpy as np + >>> import damask >>> np.set_printoptions(3,suppress=True,floatmode='fixed') >>> O = damask.Orientation.from_Euler_angles(phi=[0,45,0],degrees=True,lattice='cF') >>> O.Schmid(N_slip=[1]) @@ -936,8 +870,9 @@ class Orientation(Rotation,Crystal): Returns ------- - Orientations related to self following the selected - model for the orientation relationship. + rel : Orientation, shape (:,self.shape) + Orientations related to self according to the selected + model for the orientation relationship. Examples -------- diff --git a/python/damask/_result.py b/python/damask/_result.py index c545b52e8..e46671917 100644 --- a/python/damask/_result.py +++ b/python/damask/_result.py @@ -15,7 +15,7 @@ from typing import Optional, Union, Callable, Any, Sequence, Literal, Dict, List import h5py import numpy as np -import numpy.ma as ma +from numpy import ma import damask from . import VTK @@ -65,9 +65,9 @@ def _empty_like(dataset: np.ma.core.MaskedArray, class Result: """ - Add data to and export data from a DADF5 file. + Add data to and export data from a DADF5 (DAMASK HDF5) file. - A DADF5 (DAMASK HDF5) file contains DAMASK results. + A DADF5 file contains DAMASK results. Its group/folder structure reflects the layout in material.yaml. This class provides a customizable view on the DADF5 file. @@ -93,7 +93,7 @@ class Result: def __init__(self, fname: Union[str, Path]): """ - New result view bound to a HDF5 file. + New result view bound to a DADF5 file. Parameters ---------- @@ -106,10 +106,8 @@ class Result: self.version_major = f.attrs['DADF5_version_major'] self.version_minor = f.attrs['DADF5_version_minor'] - if self.version_major != 0 or not 12 <= self.version_minor <= 14: + if (self.version_major != 0 or not 14 <= self.version_minor <= 14) and self.version_major != 1: raise TypeError(f'unsupported DADF5 version "{self.version_major}.{self.version_minor}"') - if self.version_major == 0 and self.version_minor < 14: - self.export_simulation_setup = None # type: ignore self.structured = 'cells' in f['geometry'].attrs.keys() @@ -167,7 +165,7 @@ class Result: """ Return repr(self). - Give short human-readable summary. + Give short, human-readable summary. """ with h5py.File(self.fname,'r') as f: @@ -195,7 +193,7 @@ class Result: homogenizations: Union[None, str, Sequence[str], bool] = None, fields: Union[None, str, Sequence[str], bool] = None) -> "Result": """ - Manages the visibility of the groups. + Manage the visibility of the groups. Parameters ---------- @@ -319,15 +317,15 @@ class Result: Parameters ---------- increments: (list of) int, (list of) str, or bool, optional. - Number(s) of increments to select. + Numbers of increments to select. times: (list of) float, (list of) str, or bool, optional. - Simulation time(s) of increments to select. + Simulation times of increments to select. phases: (list of) str, or bool, optional. - Name(s) of phases to select. + Names of phases to select. homogenizations: (list of) str, or bool, optional. - Name(s) of homogenizations to select. + Names of homogenizations to select. fields: (list of) str, or bool, optional. - Name(s) of fields to select. + Names of fields to select. protected: bool, optional. Protection status of existing data. @@ -375,15 +373,15 @@ class Result: Parameters ---------- increments: (list of) int, (list of) str, or bool, optional. - Number(s) of increments to select. + Numbers of increments to select. times: (list of) float, (list of) str, or bool, optional. - Simulation time(s) of increments to select. + Simulation times of increments to select. phases: (list of) str, or bool, optional. - Name(s) of phases to select. + Names of phases to select. homogenizations: (list of) str, or bool, optional. - Name(s) of homogenizations to select. + Names of homogenizations to select. fields: (list of) str, or bool, optional. - Name(s) of fields to select. + Names of fields to select. Returns ------- @@ -418,15 +416,15 @@ class Result: Parameters ---------- increments: (list of) int, (list of) str, or bool, optional. - Number(s) of increments to select. + Numbers of increments to select. times: (list of) float, (list of) str, or bool, optional. - Simulation time(s) of increments to select. + Simulation times of increments to select. phases: (list of) str, or bool, optional. - Name(s) of phases to select. + Names of phases to select. homogenizations: (list of) str, or bool, optional. - Name(s) of homogenizations to select. + Names of homogenizations to select. fields: (list of) str, or bool, optional. - Name(s) of fields to select. + Names of fields to select. Returns ------- @@ -678,7 +676,7 @@ class Result: ... '1/m²','total mobile dislocation density') >>> r.add_calculation('np.sum(#rho_dip#,axis=1)','rho_dip_total', ... '1/m²','total dislocation dipole density') - >>> r.add_calculation('#rho_dip_total#+#rho_mob_total','rho_total', + >>> r.add_calculation('#rho_dip_total#+#rho_mob_total#','rho_total', ... '1/m²','total dislocation density') Add Mises equivalent of the Cauchy stress without storage of @@ -721,9 +719,11 @@ class Result: Parameters ---------- P : str, optional - Name of the dataset containing the first Piola-Kirchhoff stress. Defaults to 'P'. + Name of the dataset containing the first Piola-Kirchhoff stress. + Defaults to 'P'. F : str, optional - Name of the dataset containing the deformation gradient. Defaults to 'F'. + Name of the dataset containing the deformation gradient. + Defaults to 'F'. """ self._add_generic_pointwise(self._add_stress_Cauchy,{'P':P,'F':F}) @@ -1023,14 +1023,14 @@ class Result: x: str, ord: Union[None, int, float, Literal['fro', 'nuc']] = None): """ - Add the norm of vector or tensor. + Add the norm of a vector or tensor. Parameters ---------- x : str Name of vector or tensor dataset. 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. + Order of the norm. inf means NumPy's inf object. For details refer to numpy.linalg.norm. """ self._add_generic_pointwise(self._add_norm,{'x':x},{'ord':ord}) @@ -1052,7 +1052,7 @@ class Result: def add_stress_second_Piola_Kirchhoff(self, P: str = 'P', F: str = 'F'): - """ + r""" Add second Piola-Kirchhoff stress calculated from first Piola-Kirchhoff stress and deformation gradient. Parameters @@ -1064,9 +1064,10 @@ class Result: Notes ----- - The definition of the second Piola-Kirchhoff stress (S = [F^-1 P]_sym) + The definition of the second Piola-Kirchhoff stress + :math:`\vb{S} = \left(\vb{F}^{-1} \vb{P}\right)_\text{sym}` follows the standard definition in nonlinear continuum mechanics. - As such, no intermediate configuration, for instance that reached by F_p, + As such, no intermediate configuration, for instance that reached by :math:`\vb{F}_\text{p}`, is taken into account. """ @@ -1240,10 +1241,11 @@ class Result: Notes ----- - The incoporation of rotational parts into the elastic and plastic - deformation gradient requires it to use material/Lagragian strain measures - (based on 'U') for plastic strains and spatial/Eulerian strain measures - (based on 'V') for elastic strains when calculating averages. + The presence of rotational parts in the elastic and plastic deformation gradient + calls for the use of + material/Lagragian strain measures (based on 'U') for plastic strains and + spatial/Eulerian strain measures (based on 'V') for elastic strains + when calculating averages. """ self._add_generic_pointwise(self._add_strain,{'F':F},{'t':t,'m':m}) @@ -1302,7 +1304,7 @@ class Result: Notes ----- This function is only available for structured grids, - i.e. results from the grid solver. + i.e. fields resulting from the grid solver. """ self._add_generic_grid(self._add_curl,{'f':f},{'size':self.size}) @@ -1331,7 +1333,7 @@ class Result: Notes ----- This function is only available for structured grids, - i.e. results from the grid solver. + i.e. fields resulting from the grid solver. """ self._add_generic_grid(self._add_divergence,{'f':f},{'size':self.size}) @@ -1361,7 +1363,7 @@ class Result: Notes ----- This function is only available for structured grids, - i.e. results from the grid solver. + i.e. fields resulting from the grid solver. """ self._add_generic_grid(self._add_gradient,{'f':f},{'size':self.size}) @@ -1379,10 +1381,10 @@ class Result: ---------- func : function Callback function that calculates a new dataset from one or - more datasets per HDF5 group. + more datasets per DADF5 group. datasets : dictionary Details of the datasets to be used: - {arg (name to which the data is passed in func): label (in HDF5 file)}. + {arg (name to which the data is passed in func): label (in DADF5 file)}. args : dictionary, optional Arguments parsed to func. @@ -1462,10 +1464,10 @@ class Result: ---------- callback : function Callback function that calculates a new dataset from one or - more datasets per HDF5 group. + more datasets per DADF5 group. datasets : dictionary Details of the datasets to be used: - {arg (name to which the data is passed in func): label (in HDF5 file)}. + {arg (name to which the data is passed in func): label (in DADF5 file)}. args : dictionary, optional Arguments parsed to func. @@ -1500,7 +1502,7 @@ class Result: dataset.attrs['overwritten'] = True else: shape = result['data'].shape - if compress := (result['data'].size >= chunk_size*2): + if compress := result['data'].size >= chunk_size*2: chunks = (chunk_size//np.prod(shape[1:]),)+shape[1:] else: chunks = shape @@ -1828,9 +1830,10 @@ class Result: Export to VTK cell/point data. One VTK file per visible increment is created. - For point data, the VTK format is poly data (.vtp). - For cell data, either an image (.vti) or unstructured (.vtu) dataset - is written for grid-based or mesh-based simulations, respectively. + For point data, the VTK format is PolyData (.vtp). + For cell data, the file format is either ImageData (.vti) + or UnstructuredGrid (.vtu) for grid-based or mesh-based simulations, + respectively. Parameters ---------- @@ -1922,7 +1925,8 @@ class Result: def export_DADF5(self, fname, - output: Union[str, List[str]] = '*'): + output: Union[str, List[str]] = '*', + mapping = None): """ Export visible components into a new DADF5 file. @@ -1936,20 +1940,61 @@ class Result: output : (list of) str, optional Names of the datasets to export. Defaults to '*', in which case all visible datasets are exported. + mapping : numpy.ndarray of int, shape (:,:,:), optional + Indices for regridding. """ if Path(fname).expanduser().absolute() == self.fname: raise PermissionError(f'cannot overwrite {self.fname}') + + def cp(path_in,path_out,label,mapping): + if mapping is None: + path_in.copy(label,path_out) + else: + path_out.create_dataset(label,data=path_in[label][()][mapping]) + path_out[label].attrs.update(path_in[label].attrs) + + with h5py.File(self.fname,'r') as f_in, h5py.File(fname,'w') as f_out: - for k,v in f_in.attrs.items(): - f_out.attrs.create(k,v) - for g in ['setup','geometry','cell_to']: + f_out.attrs.update(f_in.attrs) + for g in ['setup','geometry'] + (['cell_to'] if mapping is None else []): f_in.copy(g,f_out) + if mapping is not None: + cells = mapping.shape + mapping_flat = mapping.flatten(order='F') + f_out['geometry'].attrs['cells'] = cells + f_out.create_group('cell_to') # ToDo: attribute missing + mappings = {'phase':{},'homogenization':{}} # type: ignore + + mapping_phase = f_in['cell_to']['phase'][()][mapping_flat] + for p in np.unique(mapping_phase['label']): + m = mapping_phase['label'] == p + mappings['phase'][p] = mapping_phase[m]['entry'] + c = np.count_nonzero(m) + mapping_phase[m] = list(zip((p,)*c,tuple(np.arange(c)))) + f_out['cell_to'].create_dataset('phase',data=mapping_phase.reshape(np.prod(mapping_flat.shape),-1)) + + mapping_homog = f_in['cell_to']['homogenization'][()][mapping] + for h in np.unique(mapping_homog['label']): + m = mapping_homog['label'] == h + mappings['homogenization'][h] = mapping_homog[m]['entry'] + c = np.count_nonzero(m) + mapping_homog[mapping_homog['label'] == h] = list(zip((h,)*c,tuple(np.arange(c)))) + f_out['cell_to'].create_dataset('homogenization',data=mapping_homog.flatten()) + + for inc in util.show_progress(self.visible['increments']): f_in.copy(inc,f_out,shallow=True) - for out in _match(output,f_in['/'.join([inc,'geometry'])].keys()): - f_in[inc]['geometry'].copy(out,f_out[inc]['geometry']) + if mapping is None: + for label in ['u_p','u_n']: + f_in[inc]['geometry'].copy(label,f_out[inc]['geometry']) + else: + u_p = f_in[inc]['geometry']['u_p'][()][mapping_flat] + f_out[inc]['geometry'].create_dataset('u_p',data=u_p) + u_n = np.zeros((len(mapping_flat),3)) # ToDo: needs implementation + f_out[inc]['geometry'].create_dataset('u_n',data=u_n) + for label in self.homogenizations: f_in[inc]['homogenization'].copy(label,f_out[inc]['homogenization'],shallow=True) @@ -1961,7 +2006,7 @@ class Result: for field in _match(self.visible['fields'],f_in['/'.join([inc,ty,label])].keys()): p = '/'.join([inc,ty,label,field]) for out in _match(output,f_in[p].keys()): - f_in[p].copy(out,f_out[p]) + cp(f_in[p],f_out[p],out,None if mapping is None else mappings[ty][label.encode()]) def export_simulation_setup(self, diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 6c5c143aa..118234bf1 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -35,8 +35,8 @@ class Rotation: Rotate vector 'a' (defined in coordinate system 'A') to coordinates 'b' expressed in system 'B': - >>> import damask >>> import numpy as np + >>> import damask >>> Q = damask.Rotation.from_random() >>> a = np.random.rand(3) >>> b = Q @ a @@ -45,8 +45,8 @@ class Rotation: Compound rotations R1 (first) and R2 (second): - >>> import damask >>> import numpy as np + >>> import damask >>> R1 = damask.Rotation.from_random() >>> R2 = damask.Rotation.from_random() >>> R = R2 * R1 @@ -69,7 +69,7 @@ class Rotation: Parameters ---------- - rotation : list, numpy.ndarray, Rotation, optional + rotation : list, numpy.ndarray, or Rotation, optional Unit quaternion in positive real hemisphere. Use .from_quaternion to perform a sanity check. Defaults to no rotation. @@ -88,7 +88,7 @@ class Rotation: """ Return repr(self). - Give short human-readable summary. + Give short, human-readable summary. """ return f'Quaternion{" " if self.quaternion.shape == (4,) else "s of shape "+str(self.quaternion.shape[:-1])+chr(10)}'\ @@ -902,7 +902,8 @@ class Rotation: return Rotation(Rotation._om2qu(om)) @staticmethod - def from_matrix(R: np.ndarray) -> 'Rotation': + def from_matrix(R: np.ndarray, + normalize: bool = False) -> 'Rotation': """ Initialize from rotation matrix. @@ -910,13 +911,17 @@ class Rotation: ---------- R : numpy.ndarray, shape (...,3,3) Rotation matrix with det(R) = 1 and R.T ∙ R = I. + normalize : bool, optional + Rescales rotation matrix to unit determinant. Defaults to False. Returns ------- new : damask.Rotation """ - return Rotation.from_basis(R) + return Rotation.from_basis(np.array(R,dtype=float) * (np.linalg.det(R)**(-1./3.))[...,np.newaxis,np.newaxis] + if normalize else + R) @staticmethod def from_parallel(a: np.ndarray, diff --git a/python/damask/_table.py b/python/damask/_table.py index e213243a4..ac19f761a 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -41,7 +41,7 @@ class Table: """ Return repr(self). - Give short human-readable summary. + Give short, human-readable summary. """ self._relabel('shapes') @@ -255,8 +255,8 @@ class Table: """ Load from ASCII table file. - Initial comments are marked by '#', the first non-comment line - containing the column labels. + Initial comments are marked by '#'. + The first non-comment line contains the column labels. - 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'. @@ -264,7 +264,7 @@ class Table: Parameters ---------- fname : file, str, or pathlib.Path - Filename or file for reading. + Filename or file to read. Returns ------- @@ -299,11 +299,18 @@ class Table: @staticmethod - def load_ang(fname: FileHandle) -> 'Table': + def load_ang(fname: FileHandle, + shapes = {'eu':3, + 'pos':2, + 'IQ':1, + 'CI':1, + 'ID':1, + 'intensity':1, + 'fit':1}) -> 'Table': """ - Load from ang file. + Load from ANG file. - A valid TSL ang file has to have the following columns: + Regular ANG files feature the following columns: - Euler angles (Bunge notation) in radians, 3 floats, label 'eu'. - Spatial position in meters, 2 floats, label 'pos'. @@ -316,7 +323,10 @@ class Table: Parameters ---------- fname : file, str, or pathlib.Path - Filename or file for reading. + Filename or file to read. + shapes : dict with str:int pairs, optional + Column labels and their width. + Defaults to standard TSL ANG format. Returns ------- @@ -338,7 +348,6 @@ class Table: data = np.loadtxt(content) - shapes = {'eu':3, 'pos':2, 'IQ':1, 'CI':1, 'ID':1, 'intensity':1, 'fit':1} if (remainder := data.shape[1]-sum(shapes.values())) > 0: shapes['unknown'] = remainder @@ -458,9 +467,9 @@ class Table: Parameters ---------- label_old : (iterable of) str - Old column label(s). + Old column labels. label_new : (iterable of) str - New column label(s). + New column labels. Returns ------- @@ -488,7 +497,7 @@ class Table: label : str or list Column labels for sorting. ascending : bool or list, optional - Set sort order. + Set sort order. Defaults to True. Returns ------- @@ -574,7 +583,7 @@ class Table: Parameters ---------- fname : file, str, or pathlib.Path - Filename or file for writing. + Filename or file to write. with_labels : bool, optional Write column labels. Defaults to True. @@ -594,4 +603,7 @@ class Table: f = util.open_text(fname,'w') f.write('\n'.join([f'# {c}' for c in self.comments] + [' '.join(labels)])+('\n' if labels else '')) - self.data.to_csv(f,sep=' ',na_rep='nan',index=False,header=False,line_terminator='\n') + try: # backward compatibility + self.data.to_csv(f,sep=' ',na_rep='nan',index=False,header=False,lineterminator='\n') + except TypeError: + self.data.to_csv(f,sep=' ',na_rep='nan',index=False,header=False,line_terminator='\n') diff --git a/python/damask/_typehints.py b/python/damask/_typehints.py index 5fcf39a41..5891e6305 100644 --- a/python/damask/_typehints.py +++ b/python/damask/_typehints.py @@ -8,6 +8,7 @@ import numpy as np FloatSequence = Union[np.ndarray,Sequence[float]] IntSequence = Union[np.ndarray,Sequence[int]] +StrSequence = Union[np.ndarray,Sequence[str]] FileHandle = Union[TextIO, str, Path] CrystalFamily = Union[None,Literal['triclinic', 'monoclinic', 'orthorhombic', 'tetragonal', 'hexagonal', 'cubic']] CrystalLattice = Union[None,Literal['aP', 'mP', 'mS', 'oP', 'oS', 'oI', 'oF', 'tP', 'tI', 'hP', 'cP', 'cI', 'cF']] diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 95eee8bd3..f8a58d73b 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -4,10 +4,54 @@ from pathlib import Path from typing import Optional, Union, Literal, List, Sequence import numpy as np -import vtk -from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk -from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray -from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np +from vtkmodules.vtkCommonCore import ( + vtkPoints, + vtkStringArray, + vtkLookupTable, +) +from vtkmodules.vtkCommonDataModel import ( + vtkDataSet, + vtkCellArray, + vtkImageData, + vtkRectilinearGrid, + vtkUnstructuredGrid, + vtkPolyData, +) +from vtkmodules.vtkIOLegacy import ( + vtkGenericDataObjectReader, + vtkDataSetWriter, +) +from vtkmodules.vtkIOXML import ( + vtkXMLImageDataReader, + vtkXMLImageDataWriter, + vtkXMLRectilinearGridReader, + vtkXMLRectilinearGridWriter, + vtkXMLUnstructuredGridReader, + vtkXMLUnstructuredGridWriter, + vtkXMLPolyDataReader, + vtkXMLPolyDataWriter, +) +from vtkmodules.vtkRenderingCore import ( + vtkDataSetMapper, + vtkActor, + vtkRenderer, + vtkRenderWindow, + vtkRenderWindowInteractor, +) +from vtkmodules.vtkRenderingAnnotation import ( + vtkScalarBarActor, +) +from vtkmodules.util.vtkConstants import ( + VTK_TRIANGLE, + VTK_QUAD, + VTK_TETRA, + VTK_HEXAHEDRON, +) +from vtkmodules.util.numpy_support import ( + numpy_to_vtk, + numpy_to_vtkIdTypeArray, + vtk_to_numpy, +) from ._typehints import FloatSequence, IntSequence from . import util @@ -23,16 +67,16 @@ class VTK: """ def __init__(self, - vtk_data: vtk.vtkDataSet): + vtk_data: vtkDataSet): """ New spatial visualization. Parameters ---------- - vtk_data : subclass of vtk.vtkDataSet + vtk_data : subclass of vtkDataSet Description of geometry and topology, optionally with attached data. - Valid types are vtk.vtkImageData, vtk.vtkUnstructuredGrid, - vtk.vtkPolyData, and vtk.vtkRectilinearGrid. + Valid types are vtkImageData, vtkUnstructuredGrid, + vtkPolyData, and vtkRectilinearGrid. """ self.vtk_data = vtk_data @@ -42,7 +86,7 @@ class VTK: """ Return repr(self). - Give short human-readable summary. + Give short, human-readable summary. """ info = [self.vtk_data.__vtkname__] @@ -76,14 +120,14 @@ class VTK: def copy(self): - if isinstance(self.vtk_data,vtk.vtkImageData): - dup = vtk.vtkImageData() - elif isinstance(self.vtk_data,vtk.vtkUnstructuredGrid): - dup = vtk.vtkUnstructuredGrid() - elif isinstance(self.vtk_data,vtk.vtkPolyData): - dup = vtk.vtkPolyData() - elif isinstance(self.vtk_data,vtk.vtkRectilinearGrid): - dup = vtk.vtkRectilinearGrid() + if isinstance(self.vtk_data,vtkImageData): + dup = vtkImageData() + elif isinstance(self.vtk_data,vtkUnstructuredGrid): + dup = vtkUnstructuredGrid() + elif isinstance(self.vtk_data,vtkPolyData): + dup = vtkPolyData() + elif isinstance(self.vtk_data,vtkRectilinearGrid): + dup = vtkRectilinearGrid() else: raise TypeError @@ -114,7 +158,7 @@ class VTK: Comments. """ - s = vtk.vtkStringArray() + s = vtkStringArray() s.SetName('comments') for c in comments: s.InsertNextValue(c) @@ -154,7 +198,7 @@ class VTK: size: FloatSequence, origin: FloatSequence = np.zeros(3)) -> 'VTK': """ - Create VTK of type vtk.vtkImageData. + Create VTK of type vtkImageData. This is the common type for grid solver results. @@ -163,7 +207,7 @@ class VTK: cells : sequence of int, len (3) Number of cells along each dimension. size : sequence of float, len (3) - Physical length along each dimension. + Edge length along each dimension. origin : sequence of float, len (3), optional Coordinates of grid origin. @@ -173,7 +217,7 @@ class VTK: VTK-based geometry without nodal or cell data. """ - vtk_data = vtk.vtkImageData() + vtk_data = vtkImageData() vtk_data.SetDimensions(*(np.array(cells)+1)) vtk_data.SetOrigin(*(np.array(origin))) vtk_data.SetSpacing(*(np.array(size)/np.array(cells))) @@ -186,7 +230,7 @@ class VTK: connectivity: np.ndarray, cell_type: str) -> 'VTK': """ - Create VTK of type vtk.vtkUnstructuredGrid. + Create VTK of type vtkUnstructuredGrid. This is the common type for mesh solver results. @@ -198,7 +242,7 @@ class VTK: Cell connectivity (0-based), first dimension determines #Cells, second dimension determines #Nodes/Cell. cell_type : str - Name of the vtk.vtkCell subclass. Tested for TRIANGLE, QUAD, TETRA, and HEXAHEDRON. + Name of the vtkCell subclass. Tested for TRIANGLE, QUAD, TETRA, and HEXAHEDRON. Returns ------- @@ -206,18 +250,18 @@ class VTK: VTK-based geometry without nodal or cell data. """ - vtk_nodes = vtk.vtkPoints() - vtk_nodes.SetData(np_to_vtk(np.ascontiguousarray(nodes))) - cells = vtk.vtkCellArray() + vtk_nodes = vtkPoints() + vtk_nodes.SetData(numpy_to_vtk(np.ascontiguousarray(nodes))) + cells = vtkCellArray() cells.SetNumberOfCells(connectivity.shape[0]) T = np.concatenate((np.ones((connectivity.shape[0],1),dtype=np.int64)*connectivity.shape[1], connectivity),axis=1).ravel() - cells.SetCells(connectivity.shape[0],np_to_vtkIdTypeArray(T,deep=True)) + cells.SetCells(connectivity.shape[0],numpy_to_vtkIdTypeArray(T,deep=True)) - vtk_data = vtk.vtkUnstructuredGrid() + vtk_data = vtkUnstructuredGrid() vtk_data.SetPoints(vtk_nodes) - cell_types = {'TRIANGLE':vtk.VTK_TRIANGLE, 'QUAD':vtk.VTK_QUAD, - 'TETRA' :vtk.VTK_TETRA, 'HEXAHEDRON':vtk.VTK_HEXAHEDRON} + cell_types = {'TRIANGLE':VTK_TRIANGLE, 'QUAD':VTK_QUAD, + 'TETRA' :VTK_TETRA, 'HEXAHEDRON':VTK_HEXAHEDRON} vtk_data.SetCells(cell_types[cell_type.split("_",1)[-1].upper()],cells) return VTK(vtk_data) @@ -226,7 +270,7 @@ class VTK: @staticmethod def from_poly_data(points: np.ndarray) -> 'VTK': """ - Create VTK of type vtk.polyData. + Create VTK of type polyData. This is the common type for point-wise data. @@ -242,15 +286,15 @@ class VTK: """ N = points.shape[0] - vtk_points = vtk.vtkPoints() - vtk_points.SetData(np_to_vtk(np.ascontiguousarray(points))) + vtk_points = vtkPoints() + vtk_points.SetData(numpy_to_vtk(np.ascontiguousarray(points))) - vtk_cells = vtk.vtkCellArray() + vtk_cells = vtkCellArray() vtk_cells.SetNumberOfCells(N) - vtk_cells.SetCells(N,np_to_vtkIdTypeArray(np.stack((np.ones (N,dtype=np.int64), + vtk_cells.SetCells(N,numpy_to_vtkIdTypeArray(np.stack((np.ones (N,dtype=np.int64), np.arange(N,dtype=np.int64)),axis=1).ravel(),deep=True)) - vtk_data = vtk.vtkPolyData() + vtk_data = vtkPolyData() vtk_data.SetPoints(vtk_points) vtk_data.SetVerts(vtk_cells) @@ -260,7 +304,7 @@ class VTK: @staticmethod def from_rectilinear_grid(grid: FloatSequence) -> 'VTK': """ - Create VTK of type vtk.vtkRectilinearGrid. + Create VTK of type vtkRectilinearGrid. Parameters ---------- @@ -273,9 +317,9 @@ class VTK: VTK-based geometry without nodal or cell data. """ - vtk_data = vtk.vtkRectilinearGrid() + vtk_data = vtkRectilinearGrid() vtk_data.SetDimensions(*map(len,grid)) - coord = [np_to_vtk(np.array(grid[i]),deep=True) for i in [0,1,2]] + coord = [numpy_to_vtk(np.array(grid[i]),deep=True) for i in [0,1,2]] [coord[i].SetName(n) for i,n in enumerate(['x','y','z'])] vtk_data.SetXCoordinates(coord[0]) vtk_data.SetYCoordinates(coord[1]) @@ -293,10 +337,10 @@ class VTK: Parameters ---------- fname : str or pathlib.Path - Filename for reading. + Filename to read. Valid extensions are .vti, .vtu, .vtp, .vtr, and .vtk. dataset_type : {'ImageData', 'UnstructuredGrid', 'PolyData', 'RectilinearGrid'}, optional - Name of the vtk.vtkDataSet subclass when opening a .vtk file. + Name of the vtkDataSet subclass when opening a .vtk file. Returns ------- @@ -307,7 +351,7 @@ class VTK: if not Path(fname).expanduser().is_file(): # vtk has a strange error handling raise FileNotFoundError(f'file "{fname}" not found') if (ext := Path(fname).suffix) == '.vtk' or dataset_type is not None: - reader = vtk.vtkGenericDataObjectReader() + reader = vtkGenericDataObjectReader() reader.SetFileName(str(Path(fname).expanduser())) if dataset_type is None: raise TypeError('dataset type for *.vtk file not given') @@ -327,13 +371,13 @@ class VTK: raise TypeError(f'unknown dataset type "{dataset_type}" for vtk file') else: if ext == '.vti': - reader = vtk.vtkXMLImageDataReader() + reader = vtkXMLImageDataReader() elif ext == '.vtu': - reader = vtk.vtkXMLUnstructuredGridReader() + reader = vtkXMLUnstructuredGridReader() elif ext == '.vtp': - reader = vtk.vtkXMLPolyDataReader() + reader = vtkXMLPolyDataReader() elif ext == '.vtr': - reader = vtk.vtkXMLRectilinearGridReader() + reader = vtkXMLRectilinearGridReader() else: raise TypeError(f'unknown file extension "{ext}"') @@ -352,7 +396,7 @@ class VTK: def as_ASCII(self) -> str: """ASCII representation of the VTK data.""" - writer = vtk.vtkDataSetWriter() + writer = vtkDataSetWriter() writer.SetHeader(f'# {util.execution_stamp("VTK")}') writer.WriteToOutputStringOn() writer.SetInputData(self.vtk_data) @@ -370,21 +414,21 @@ class VTK: Parameters ---------- fname : str or pathlib.Path - Filename for writing. + Filename to write. parallel : bool, optional Write data in parallel background process. Defaults to True. compress : bool, optional Compress with zlib algorithm. Defaults to True. """ - if isinstance(self.vtk_data,vtk.vtkImageData): - writer = vtk.vtkXMLImageDataWriter() - elif isinstance(self.vtk_data,vtk.vtkUnstructuredGrid): - writer = vtk.vtkXMLUnstructuredGridWriter() - elif isinstance(self.vtk_data,vtk.vtkPolyData): - writer = vtk.vtkXMLPolyDataWriter() - elif isinstance(self.vtk_data,vtk.vtkRectilinearGrid): - writer = vtk.vtkXMLRectilinearGridWriter() + if isinstance(self.vtk_data,vtkImageData): + writer = vtkXMLImageDataWriter() + elif isinstance(self.vtk_data,vtkUnstructuredGrid): + writer = vtkXMLUnstructuredGridWriter() + elif isinstance(self.vtk_data,vtkPolyData): + writer = vtkXMLPolyDataWriter() + elif isinstance(self.vtk_data,vtkRectilinearGrid): + writer = vtkXMLRectilinearGridWriter() default_ext = '.'+writer.GetDefaultFileExtension() ext = Path(fname).suffix @@ -433,6 +477,11 @@ class VTK: Data to add or replace. Each table label is individually considered. Number of rows needs to match either number of cells or number of points. + Returns + ------- + updated : damask.VTK + Updated VTK-based geometry. + Notes ----- If the number of cells equals the number of points, the data is added to both. @@ -451,11 +500,11 @@ class VTK: .astype(np.single if data.dtype in [np.double,np.longdouble] else data.dtype) if data.dtype.type is np.str_: - d = vtk.vtkStringArray() + d = vtkStringArray() for s in np.squeeze(data_): d.InsertNextValue(s) else: - d = np_to_vtk(data_,deep=True) + d = numpy_to_vtk(data_,deep=True) d.SetName(label) @@ -513,7 +562,7 @@ class VTK: for a in range(cell_data.GetNumberOfArrays()): if cell_data.GetArrayName(a) == label: try: - return vtk_to_np(cell_data.GetArray(a)) + return vtk_to_numpy(cell_data.GetArray(a)) except AttributeError: vtk_array = cell_data.GetAbstractArray(a) # string array @@ -521,7 +570,7 @@ class VTK: for a in range(point_data.GetNumberOfArrays()): if point_data.GetArrayName(a) == label: try: - return vtk_to_np(point_data.GetArray(a)) + return vtk_to_numpy(point_data.GetArray(a)) except AttributeError: vtk_array = point_data.GetAbstractArray(a) # string array @@ -548,7 +597,7 @@ class VTK: Notes ----- The first component is shown when visualizing vector datasets - (this includes tensor datasets because they are flattened). + (this includes tensor datasets as they are flattened). """ # See http://compilatrix.com/article/vtk-1 for possible improvements. @@ -567,7 +616,7 @@ class VTK: width = 1024 height = 768 - lut = vtk.vtkLookupTable() + lut = vtkLookupTable() colormap_ = Colormap.from_predefined(colormap) if isinstance(colormap,str) else \ colormap lut.SetNumberOfTableValues(len(colormap_.colors)) @@ -576,33 +625,33 @@ class VTK: lut.Build() self.vtk_data.GetCellData().SetActiveScalars(label) - mapper = vtk.vtkDataSetMapper() + mapper = vtkDataSetMapper() mapper.SetInputData(self.vtk_data) mapper.SetLookupTable(lut) mapper.SetScalarRange(self.vtk_data.GetScalarRange()) - actor = vtk.vtkActor() + actor = vtkActor() actor.SetMapper(mapper) actor.GetProperty().SetColor(230/255,150/255,68/255) - ren = vtk.vtkRenderer() + ren = vtkRenderer() ren.AddActor(actor) if label is None: ren.SetBackground(67/255,128/255,208/255) else: - colormap_vtk = vtk.vtkScalarBarActor() + colormap_vtk = vtkScalarBarActor() colormap_vtk.SetLookupTable(lut) colormap_vtk.SetTitle(label) colormap_vtk.SetMaximumWidthInPixels(width//100) ren.AddActor2D(colormap_vtk) ren.SetBackground(0.3,0.3,0.3) - window = vtk.vtkRenderWindow() + window = vtkRenderWindow() window.AddRenderer(ren) window.SetSize(width,height) window.SetWindowName(util.execution_stamp('VTK','show')) - iren = vtk.vtkRenderWindowInteractor() + iren = vtkRenderWindowInteractor() iren.SetRenderWindow(window) if os.name == 'posix' and 'DISPLAY' not in os.environ: print('Found no rendering device') diff --git a/python/damask/grid_filters.py b/python/damask/grid_filters.py index fab346c4e..462621e53 100644 --- a/python/damask/grid_filters.py +++ b/python/damask/grid_filters.py @@ -402,7 +402,7 @@ def displacement_node(size: _FloatSequence, Returns ------- - u_p : numpy.ndarray, shape (:,:,:,3) + u_n : numpy.ndarray, shape (:,:,:,3) Nodal displacements. """ @@ -564,17 +564,10 @@ def unravel_index(idx: _np.ndarray) -> _np.ndarray: >>> seq = np.arange(6).reshape((3,2,1),order='F') >>> (coord_idx := damask.grid_filters.unravel_index(seq)) array([[[[0, 0, 0]], - [[0, 1, 0]]], - - [[[1, 0, 0]], - [[1, 1, 0]]], - - [[[2, 0, 0]], - [[2, 1, 0]]]]) >>> coord_idx[1,1,0] array([1, 1, 0]) @@ -608,17 +601,12 @@ def ravel_index(idx: _np.ndarray) -> _np.ndarray: >>> import damask >>> (rev := np.array([[1,1,0],[0,1,0],[1,0,0],[0,0,0]]).reshape((2,2,1,3))) array([[[[1, 1, 0]], - [[0, 1, 0]]], - - [[[1, 0, 0]], - [[0, 0, 0]]]]) >>> (flat_idx := damask.grid_filters.ravel_index(rev)) array([[[3], [2]], - [[1], [0]]]) diff --git a/python/damask/mechanics.py b/python/damask/mechanics.py index 76c7ae13b..2d6078680 100644 --- a/python/damask/mechanics.py +++ b/python/damask/mechanics.py @@ -5,7 +5,7 @@ All routines operate on numpy.ndarrays of shape (...,3,3). """ -from typing import Sequence as _Sequence +from typing import Sequence as _Sequence#, Literal as _Literal import numpy as _np @@ -14,7 +14,7 @@ from . import _rotation def deformation_Cauchy_Green_left(F: _np.ndarray) -> _np.ndarray: - """ + r""" Calculate left Cauchy-Green deformation tensor (Finger deformation tensor). Parameters @@ -27,12 +27,18 @@ def deformation_Cauchy_Green_left(F: _np.ndarray) -> _np.ndarray: B : numpy.ndarray, shape (...,3,3) Left Cauchy-Green deformation tensor. + Notes + ----- + .. math:: + + \vb{B} = \vb{F} \vb{F}^\text{T} + """ return _np.matmul(F,_tensor.transpose(F)) def deformation_Cauchy_Green_right(F: _np.ndarray) -> _np.ndarray: - """ + r""" Calculate right Cauchy-Green deformation tensor. Parameters @@ -45,12 +51,18 @@ def deformation_Cauchy_Green_right(F: _np.ndarray) -> _np.ndarray: C : numpy.ndarray, shape (...,3,3) Right Cauchy-Green deformation tensor. + Notes + ----- + .. math:: + + \vb{C} = \vb{F}^\text{T} \vb{F} + """ return _np.matmul(_tensor.transpose(F),F) def equivalent_strain_Mises(epsilon: _np.ndarray) -> _np.ndarray: - """ + r""" Calculate the Mises equivalent of a strain tensor. Parameters @@ -63,12 +75,23 @@ def equivalent_strain_Mises(epsilon: _np.ndarray) -> _np.ndarray: epsilon_vM : numpy.ndarray, shape (...) Von Mises equivalent strain of epsilon. + Notes + ----- + The von Mises equivalent of a strain tensor is defined as: + + .. math:: + + \epsilon_\text{vM} = \sqrt{\frac{2}{3}\,\epsilon^\prime_{ij} \epsilon^\prime_{ij}} + + where :math:`\vb*{\epsilon}^\prime` is the deviatoric part + of the strain tensor. + """ return _equivalent_Mises(epsilon,2.0/3.0) def equivalent_stress_Mises(sigma: _np.ndarray) -> _np.ndarray: - """ + r""" Calculate the Mises equivalent of a stress tensor. Parameters @@ -81,6 +104,17 @@ def equivalent_stress_Mises(sigma: _np.ndarray) -> _np.ndarray: sigma_vM : numpy.ndarray, shape (...) Von Mises equivalent stress of sigma. + Notes + ----- + The von Mises equivalent of a stress tensor is defined as: + + .. math:: + + \sigma_\text{vM} = \sqrt{\frac{3}{2}\,\sigma^\prime_{ij} \sigma^\prime_{ij}} + + where :math:`\vb*{\sigma}^\prime` is the deviatoric part + of the stress tensor. + """ return _equivalent_Mises(sigma,3.0/2.0) @@ -105,7 +139,7 @@ def maximum_shear(T_sym: _np.ndarray) -> _np.ndarray: def rotation(T: _np.ndarray) -> _rotation.Rotation: - """ + r""" Calculate the rotational part of a tensor. Parameters @@ -118,23 +152,35 @@ def rotation(T: _np.ndarray) -> _rotation.Rotation: R : damask.Rotation, shape (...) Rotational part of the vector. + Notes + ----- + The rotational part is calculated from the polar decomposition: + + .. math:: + + \vb{R} = \vb{T} \vb{U}^{-1} = \vb{V}^{-1} \vb{T} + + where :math:`\vb{V}` and :math:`\vb{U}` are the left + and right stretch tensor, respectively. + """ return _rotation.Rotation.from_matrix(_polar_decomposition(T,'R')[0]) def strain(F: _np.ndarray, + #t: _Literal['V', 'U'], should work, but rejected by SC t: str, m: float) -> _np.ndarray: - """ + r""" Calculate strain tensor (Seth–Hill family). Parameters ---------- F : numpy.ndarray, shape (...,3,3) Deformation gradient. - t : {‘V’, ‘U’} - Type of the polar decomposition, ‘V’ for left stretch tensor - and ‘U’ for right stretch tensor. + t : {'V', 'U'} + Type of the polar decomposition, 'V' for left stretch tensor + or 'U' for right stretch tensor. m : float Order of the strain. @@ -143,25 +189,25 @@ def strain(F: _np.ndarray, epsilon : numpy.ndarray, shape (...,3,3) Strain of F. + Notes + ----- + The strain is defined as: + + .. math:: + + \vb*{\epsilon}_V^{(m)} = \frac{1}{2m} (\vb{V}^{2m} - \vb{I}) \\\\ + \vb*{\epsilon}_U^{(m)} = \frac{1}{2m} (\vb{U}^{2m} - \vb{I}) + References ---------- - https://en.wikipedia.org/wiki/Finite_strain_theory - https://de.wikipedia.org/wiki/Verzerrungstensor + | https://en.wikipedia.org/wiki/Finite_strain_theory + | https://de.wikipedia.org/wiki/Verzerrungstensor """ - if t == 'V': - w,n = _np.linalg.eigh(deformation_Cauchy_Green_left(F)) - elif t == 'U': - w,n = _np.linalg.eigh(deformation_Cauchy_Green_right(F)) - - if m > 0.0: - eps = 1.0/(2.0*abs(m)) * (+ _np.einsum('...j,...kj,...lj',w**m,n,n) - _np.eye(3)) - elif m < 0.0: - eps = 1.0/(2.0*abs(m)) * (- _np.einsum('...j,...kj,...lj',w**m,n,n) + _np.eye(3)) - else: - eps = _np.einsum('...j,...kj,...lj',0.5*_np.log(w),n,n) - - return eps + if t not in ['V', 'U']: raise ValueError('polar decomposition type not in {V, U}') + w,n = _np.linalg.eigh(deformation_Cauchy_Green_left(F) if t=='V' else deformation_Cauchy_Green_right(F)) + return 0.5 * _np.einsum('...j,...kj,...lj',_np.log(w),n,n) if m == 0.0 \ + else 0.5/m * (_np.einsum('...j,...kj,...lj', w**m,n,n) - _np.eye(3)) def stress_Cauchy(P: _np.ndarray, @@ -212,7 +258,7 @@ def stress_second_Piola_Kirchhoff(P: _np.ndarray, def stretch_left(T: _np.ndarray) -> _np.ndarray: - """ + r""" Calculate left stretch of a tensor. Parameters @@ -225,12 +271,23 @@ def stretch_left(T: _np.ndarray) -> _np.ndarray: V : numpy.ndarray, shape (...,3,3) Left stretch tensor from Polar decomposition of T. + Notes + ----- + The left stretch tensor is calculated from the + polar decomposition: + + .. math:: + + \vb{V} = \vb{T} \vb{R}^\text{T} + + where :math:`\vb{R}` is a rotation. + """ return _polar_decomposition(T,'V')[0] def stretch_right(T: _np.ndarray) -> _np.ndarray: - """ + r""" Calculate right stretch of a tensor. Parameters @@ -243,6 +300,17 @@ def stretch_right(T: _np.ndarray) -> _np.ndarray: U : numpy.ndarray, shape (...,3,3) Left stretch tensor from Polar decomposition of T. + Notes + ----- + The right stretch tensor is calculated from the + polar decomposition: + + .. math:: + + \vb{U} = \vb{R}^\text{T} \vb{T} + + where :math:`\vb{R}` is a rotation. + """ return _polar_decomposition(T,'U')[0] @@ -257,8 +325,13 @@ def _polar_decomposition(T: _np.ndarray, T : numpy.ndarray, shape (...,3,3) Tensor of which the singular values are computed. requested : sequence of {'R', 'U', 'V'} - Requested outputs: ‘R’ for the rotation tensor, - ‘V’ for left stretch tensor, and ‘U’ for right stretch tensor. + Requested outputs: 'R' for the rotation tensor, + 'V' for left stretch tensor, and 'U' for right stretch tensor. + + Returns + ------- + VRU : tuple of numpy.ndarray, shape (...,3,3) + Requested components of the singular value decomposition. """ u, _, vh = _np.linalg.svd(T) @@ -290,6 +363,11 @@ def _equivalent_Mises(T_sym: _np.ndarray, s : float Scaling factor (2/3 for strain, 3/2 for stress). + Returns + ------- + eq : numpy.ndarray, shape (...) + Scaled second invariant of the deviatoric part of T_sym. + """ d = _tensor.deviatoric(T_sym) return _np.sqrt(s*_np.sum(d**2.0,axis=(-1,-2))) diff --git a/python/damask/seeds.py b/python/damask/seeds.py index f8cb19995..808ad3c1b 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -21,7 +21,7 @@ def from_random(size: _FloatSequence, Parameters ---------- size : sequence of float, len (3) - Physical size of the seeding domain. + Edge lengths of the seeding domain. N_seeds : int Number of seeds. cells : sequence of int, len (3), optional. @@ -56,12 +56,12 @@ def from_Poisson_disc(size: _FloatSequence, periodic: bool = True, rng_seed: _Optional[_NumpyRngSeed] = None) -> _np.ndarray: """ - Place seeds according to a Poisson disc distribution. + Place seeds following a Poisson disc distribution. Parameters ---------- size : sequence of float, len (3) - Physical size of the seeding domain. + Edge lengths of the seeding domain. N_seeds : int Number of seeds. N_candidates : int @@ -70,6 +70,7 @@ def from_Poisson_disc(size: _FloatSequence, Minimum acceptable distance to other seeds. periodic : bool, optional Calculate minimum distance for periodically repeated grid. + Defaults to True. rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None. If None, then fresh, unpredictable entropy will be pulled from the OS. @@ -123,14 +124,36 @@ def from_grid(grid, Consider all material IDs except those in selection. Defaults to False. average : bool, optional Seed corresponds to center of gravity of material ID cloud. + Defaults to False. periodic : bool, optional Center of gravity accounts for periodic boundaries. + Defaults to True. Returns ------- coords, materials : numpy.ndarray, shape (:,3); numpy.ndarray, shape (:) Seed coordinates in 3D space, material IDs. + Examples + -------- + Recreate seeds from Voronoi tessellation. + + >>> import numpy as np + >>> import scipy.spatial + >>> import damask + >>> seeds = damask.seeds.from_random(np.ones(3),29,[128]*3) + >>> (g := damask.Grid.from_Voronoi_tessellation([128]*3,np.ones(3),seeds)) + cells: 128 × 128 × 128 + size: 1.0 × 1.0 × 1.0 m³ + origin: 0.0 0.0 0.0 m + # materials: 29 + >>> COG,matID = damask.seeds.from_grid(g,average=True) + >>> distance,ID = scipy.spatial.KDTree(COG,boxsize=g.size).query(seeds) + >>> np.max(distance) / np.linalg.norm(g.size/g.cells) + 7.8057356746350415 + >>> (ID == matID).all() + True + """ material = grid.material.reshape((-1,1),order='F') mask = _np.full(grid.cells.prod(),True,dtype=bool) if selection is None else \ diff --git a/python/damask/solver/_marc.py b/python/damask/solver/_marc.py index 1afb5ddc6..18bd56e49 100644 --- a/python/damask/solver/_marc.py +++ b/python/damask/solver/_marc.py @@ -2,6 +2,7 @@ import subprocess import shlex import re from pathlib import Path +from typing import Literal _marc_version = '2022.4' _marc_root = '/opt/msc' @@ -54,7 +55,7 @@ class Marc: def submit_job(self, model: str, job: str, compile: bool = False, - optimization: str = '', + optimization: Literal['', 'l', 'h'] = '', env = None): """ Assemble command line arguments and call Marc executable. @@ -68,8 +69,8 @@ class Marc: compile : bool, optional Compile DAMASK_Marc user subroutine (and save for future use). Defaults to False. - optimization : str, optional - Optimization level '' (-O0), 'l' (-O1), or 'h' (-O3). + optimization : {'', 'l', 'h'}, optional + Optimization level '': -O0, 'l': -O1, or 'h': -O3. Defaults to ''. env : dict, optional Environment for execution. diff --git a/python/damask/util.py b/python/damask/util.py index 666bffc0b..d61ca221b 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -8,8 +8,9 @@ import shlex as _shlex import re as _re import signal as _signal import fractions as _fractions -from collections import abc as _abc -from functools import reduce as _reduce, partial as _partial +from collections import abc as _abc, OrderedDict as _OrderedDict +from functools import reduce as _reduce, partial as _partial, wraps as _wraps +import inspect from typing import Optional as _Optional, Callable as _Callable, Union as _Union, Iterable as _Iterable, \ Dict as _Dict, List as _List, Tuple as _Tuple, Literal as _Literal, \ Any as _Any, TextIO as _TextIO @@ -540,10 +541,11 @@ def shapeblender(a: _Tuple[int, ...], def _docstringer(docstring: _Union[str, _Callable], - extra_parameters: _Optional[str] = None, - # extra_examples: _Optional[str] = None, - # extra_notes: _Optional[str] = None, - return_type: _Union[None, str, _Callable] = None) -> str: + adopted_parameters: _Union[None, str, _Callable] = None, + adopted_return: _Union[None, str, _Callable] = None, + adopted_notes: _Union[None, str, _Callable] = None, + adopted_examples: _Union[None, str, _Callable] = None, + adopted_references: _Union[None, str, _Callable] = None) -> str: """ Extend a docstring. @@ -551,50 +553,85 @@ def _docstringer(docstring: _Union[str, _Callable], ---------- docstring : str or callable, optional Docstring (of callable) to extend. - extra_parameters : str, optional - Additional information to append to Parameters section. - return_type : str or callable, optional - Type of return variable. + adopted_* : str or callable, optional + Additional information to insert into/append to respective section. + + Notes + ----- + adopted_return fetches the typehint of a passed function instead of the docstring """ - docstring_ = str( docstring if isinstance(docstring,str) - else docstring.__doc__ if hasattr(docstring,'__doc__') - else '') - d = dict(Parameters=extra_parameters, - # Examples=extra_examples, - # Notes=extra_notes, - ) - for key,extra in [(k,v) for (k,v) in d.items() if v is not None]: - if not (heading := _re.search(fr'^([ ]*){key}\s*\n\1{"-"*len(key)}', - docstring_,flags=_re.MULTILINE)): - raise RuntimeError(f"Docstring {docstring_} lacks a correctly formatted {key} section to insert values into") - content = [line for line in extra.split('\n') if line.strip()] - indent = len(heading.group(1)) - shift = min([len(line)-len(line.lstrip(' '))-indent for line in content]) - extra = '\n'.join([(line[shift:] if shift > 0 else - f'{" "*-shift}{line}') for line in content]) - docstring_ = _re.sub(fr'(^([ ]*){key}\s*\n\2{"-"*len(key)}[\n ]*[A-Za-z0-9_ ]*: ([^\n]+\n)*)', - fr'\1{extra}\n', - docstring_,flags=_re.MULTILINE) + docstring_: str = str( docstring if isinstance(docstring,str) + else docstring.__doc__ if callable(docstring) and docstring.__doc__ + else '').rstrip()+'\n' + sections = _OrderedDict( + Parameters=adopted_parameters, + Returns=adopted_return, + Examples=adopted_examples, + Notes=adopted_notes, + References=adopted_references) - if return_type is None: - return docstring_ - else: - if isinstance(return_type,str): - return_type_ = return_type + for i, (key, adopted) in [(i,(k,v)) for (i,(k,v)) in enumerate(sections.items()) if v is not None]: + section_regex = fr'^([ ]*){key}\s*\n\1*{"-"*len(key)}\s*\n' + if key=='Returns': + if callable(adopted): + return_class = adopted.__annotations__.get('return','') + return_type_ = (_sys.modules[adopted.__module__].__name__.split('.')[0] + +'.' + +(return_class.__name__ if not isinstance(return_class,str) else return_class)) + else: + return_type_ = adopted + docstring_ = _re.sub(fr'(^[ ]*{key}\s*\n\s*{"-"*len(key)}\s*\n[ ]*[A-Za-z0-9_ ]*: )(.*)\n', + fr'\1{return_type_}\n', + docstring_,flags=_re.MULTILINE) else: - return_class = return_type.__annotations__.get('return','') - return_type_ = (_sys.modules[return_type.__module__].__name__.split('.')[0] - +'.' - +(return_class.__name__ if not isinstance(return_class,str) else return_class) - ) + section_content_regex = fr'{section_regex}(?P.*?)\n *(\n|\Z)' + adopted_: str = adopted.__doc__ if callable(adopted) else adopted #type: ignore + try: + if _re.search(fr'{section_regex}', adopted_, flags=_re.MULTILINE): + adopted_ = _re.search(section_content_regex, #type: ignore + adopted_, + flags=_re.MULTILINE|_re.DOTALL).group('content') + except AttributeError: + raise RuntimeError(f"Function docstring passed for docstring section '{key}' is invalid:\n{docstring}") + + docstring_indent, adopted_indent = (min([len(line)-len(line.lstrip()) for line in section.split('\n') if line.strip()]) + for section in [docstring_, adopted_]) + shift = adopted_indent - docstring_indent + adopted_content = '\n'.join([(line[shift:] if shift > 0 else + f'{" "*-shift}{line}') for line in adopted_.split('\n') if line.strip()]) + + if _re.search(section_regex, docstring_, flags=_re.MULTILINE): + docstring_section_content = _re.search(section_content_regex, # type: ignore + docstring_, + flags=_re.MULTILINE|_re.DOTALL).group('content') + a_items, d_items = (_re.findall('^[ ]*([A-Za-z0-9_ ]*?)[ ]*:',content,flags=_re.MULTILINE) + for content in [adopted_content,docstring_section_content]) + for item in a_items: + if item in d_items: + adopted_content = _re.sub(fr'^([ ]*){item}.*?(?:(\n)\1([A-Za-z0-9_])|([ ]*\Z))', + r'\1\3', + adopted_content, + flags=_re.MULTILINE|_re.DOTALL).rstrip(' \n') + docstring_ = _re.sub(fr'(^[ ]*{key}\s*\n\s*{"-"*len(key)}\s*\n.*?)\n *(\Z|\n)', + fr'\1\n{adopted_content}\n\2', + docstring_, + flags=_re.MULTILINE|_re.DOTALL) + else: + section_title = f'{" "*(shift+docstring_indent)}{key}\n{" "*(shift+docstring_indent)}{"-"*len(key)}\n' + section_matches = [_re.search( + fr'[ ]*{list(sections.keys())[index]}\s*\n\s*{"-"*len(list(sections.keys())[index])}\s*', docstring_) + for index in range(i,len(sections))] + subsequent_section = '\\Z' if not any(section_matches) else \ + '\n'+next(item for item in section_matches if item is not None).group(0) + docstring_ = _re.sub(fr'({subsequent_section})', + fr'\n{section_title}{adopted_content}\n\1', + docstring_) + return docstring_ - return _re.sub(r'(^([ ]*)Returns\s*\n\2-------\s*\n[ ]*[A-Za-z0-9_ ]*: )(.*)\n', - fr'\1{return_type_}\n', - docstring_,flags=_re.MULTILINE) def extend_docstring(docstring: _Union[None, str, _Callable] = None, - extra_parameters: _Optional[str] = None) -> _Callable: + **kwargs) -> _Callable: """ Decorator: Extend the function's docstring. @@ -602,8 +639,8 @@ def extend_docstring(docstring: _Union[None, str, _Callable] = None, ---------- docstring : str or callable, optional Docstring to extend. Defaults to that of decorated function. - extra_parameters : str, optional - Additional information to append to Parameters section. + adopted_* : str or callable, optional + Additional information to insert into/append to respective section. Notes ----- @@ -611,13 +648,55 @@ def extend_docstring(docstring: _Union[None, str, _Callable] = None, """ def _decorator(func): + if 'adopted_return' not in kwargs: kwargs['adopted_return'] = func func.__doc__ = _docstringer(func.__doc__ if docstring is None else docstring, - extra_parameters, - func if isinstance(docstring,_Callable) else None, - ) + **kwargs) return func return _decorator +def pass_on(keyword: str, + target: _Callable, + wrapped: _Callable = None) -> _Callable: # type: ignore + """ + Decorator: Combine signatures of 'wrapped' and 'target' functions and pass on output of 'target' as 'keyword' argument. + + Parameters + ---------- + keyword : str + Keyword added to **kwargs of the decorated function + passing on the result of 'target'. + target : callable + The output of this function is passed to the + decorated function as 'keyword' argument. + wrapped: callable, optional + Signature of 'wrapped' function combined with + that of 'target' yields the overall signature of decorated function. + + Notes + ----- + The keywords used by 'target' will be prioritized + if they overlap with those of the decorated function. + Functions 'target' and 'wrapped' are assumed to only have keyword arguments. + + """ + + def decorator(func): + @_wraps(func) + def wrapper(*args, **kwargs): + kw_wrapped = set(kwargs.keys()) - set(inspect.getfullargspec(target).args) + kwargs_wrapped = {kw: kwargs.pop(kw) for kw in kw_wrapped} + kwargs_wrapped[keyword] = target(**kwargs) + return func(*args, **kwargs_wrapped) + args_ = [] if wrapped is None or 'self' not in inspect.signature(wrapped).parameters \ + else [inspect.signature(wrapped).parameters['self']] + for f in [target] if wrapped is None else [target,wrapped]: + for param in inspect.signature(f).parameters.values(): + if param.name != keyword \ + and param.name not in [p.name for p in args_]+['self','cls', 'args', 'kwargs']: + args_.append(param.replace(kind=inspect._ParameterKind.KEYWORD_ONLY)) + wrapper.__signature__ = inspect.Signature(parameters=args_,return_annotation=inspect.signature(func).return_annotation) + return wrapper + return decorator def DREAM3D_base_group(fname: _Union[str, _Path]) -> str: """ @@ -800,7 +879,7 @@ class ProgressBar: prefix: str, bar_length: int): """ - Set current time as basis for ETA estimation. + New progress bar. Parameters ---------- diff --git a/python/mypy.ini b/python/mypy.ini index 5ef04daee..f64c9b8dd 100644 --- a/python/mypy.ini +++ b/python/mypy.ini @@ -4,7 +4,7 @@ warn_redundant_casts = True ignore_missing_imports = True [mypy-h5py.*] ignore_missing_imports = True -[mypy-vtk.*] +[mypy-vtkmodules.*] ignore_missing_imports = True [mypy-PIL.*] ignore_missing_imports = True diff --git a/python/setup.cfg b/python/setup.cfg index e183e6b3f..49cc08fe2 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -26,4 +26,3 @@ install_requires = vtk>=8.1 matplotlib>=3.0 # requires numpy, pillow pyyaml>=3.12 -setup_requires = setuptools diff --git a/python/tests/conftest.py b/python/tests/conftest.py index 15495f9b8..dc4b44a6a 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -60,9 +60,9 @@ def update(request): @pytest.fixture -def ref_path_base(): - """Directory containing reference results.""" - return Path(__file__).parent/'reference' +def res_path_base(): + """Directory containing testing resources.""" + return Path(__file__).parent/'resources' @pytest.fixture diff --git a/python/tests/reference/Result/12grains6x7x8_tensionY.hdf5 b/python/tests/reference/Result/12grains6x7x8_tensionY.hdf5 deleted file mode 100644 index de5082a0d..000000000 Binary files a/python/tests/reference/Result/12grains6x7x8_tensionY.hdf5 and /dev/null differ diff --git a/python/tests/reference/Result/12grains6x7x8_tensionY_restart.hdf5 b/python/tests/reference/Result/12grains6x7x8_tensionY_restart.hdf5 deleted file mode 100644 index d3c5a8004..000000000 Binary files a/python/tests/reference/Result/12grains6x7x8_tensionY_restart.hdf5 and /dev/null differ diff --git a/python/tests/reference/Result/12grains6x7x8_tensionY_restart_restart.hdf5 b/python/tests/reference/Result/12grains6x7x8_tensionY_restart_restart.hdf5 deleted file mode 100644 index 64430ba9a..000000000 Binary files a/python/tests/reference/Result/12grains6x7x8_tensionY_restart_restart.hdf5 and /dev/null differ diff --git a/python/tests/reference/Result/6grains6x7x8_single_phase_tensionY.hdf5 b/python/tests/reference/Result/6grains6x7x8_single_phase_tensionY.hdf5 deleted file mode 100644 index cb7838332..000000000 Binary files a/python/tests/reference/Result/6grains6x7x8_single_phase_tensionY.hdf5 and /dev/null differ diff --git a/python/tests/reference/Result/check_compile_job1.hdf5 b/python/tests/reference/Result/check_compile_job1.hdf5 deleted file mode 100644 index 2634c26ce..000000000 Binary files a/python/tests/reference/Result/check_compile_job1.hdf5 and /dev/null differ diff --git a/python/tests/reference/Result/export_VTK/test_export_vtk[0-0-1].md5 b/python/tests/reference/Result/export_VTK/test_export_vtk[0-0-1].md5 deleted file mode 100644 index 20beaee70..000000000 --- a/python/tests/reference/Result/export_VTK/test_export_vtk[0-0-1].md5 +++ /dev/null @@ -1 +0,0 @@ -27972d6a0955e4e6e27a6ac5762abda8 diff --git a/python/tests/reference/Result/export_VTK/test_export_vtk[1-0-1].md5 b/python/tests/reference/Result/export_VTK/test_export_vtk[1-0-1].md5 deleted file mode 100644 index 9f551820c..000000000 --- a/python/tests/reference/Result/export_VTK/test_export_vtk[1-0-1].md5 +++ /dev/null @@ -1 +0,0 @@ -dd71d25ccb52c3fdfd2ab727fc852a98 diff --git a/python/tests/reference/Colormap/binary.json b/python/tests/resources/Colormap/binary.json similarity index 100% rename from python/tests/reference/Colormap/binary.json rename to python/tests/resources/Colormap/binary.json diff --git a/python/tests/reference/Colormap/binary.legend b/python/tests/resources/Colormap/binary.legend similarity index 100% rename from python/tests/reference/Colormap/binary.legend rename to python/tests/resources/Colormap/binary.legend diff --git a/python/tests/reference/Colormap/binary.msh b/python/tests/resources/Colormap/binary.msh similarity index 100% rename from python/tests/reference/Colormap/binary.msh rename to python/tests/resources/Colormap/binary.msh diff --git a/python/tests/reference/Colormap/binary.txt b/python/tests/resources/Colormap/binary.txt similarity index 100% rename from python/tests/reference/Colormap/binary.txt rename to python/tests/resources/Colormap/binary.txt diff --git a/python/tests/reference/Colormap/shade_None.png b/python/tests/resources/Colormap/shade_None.png similarity index 100% rename from python/tests/reference/Colormap/shade_None.png rename to python/tests/resources/Colormap/shade_None.png diff --git a/python/tests/reference/Colormap/shade_[2, 10].png b/python/tests/resources/Colormap/shade_[2, 10].png similarity index 100% rename from python/tests/reference/Colormap/shade_[2, 10].png rename to python/tests/resources/Colormap/shade_[2, 10].png diff --git a/python/tests/reference/ConfigMaterial/2phase_irregularGrid.dream3d b/python/tests/resources/ConfigMaterial/2phase_irregularGrid.dream3d similarity index 100% rename from python/tests/reference/ConfigMaterial/2phase_irregularGrid.dream3d rename to python/tests/resources/ConfigMaterial/2phase_irregularGrid.dream3d diff --git a/python/tests/reference/ConfigMaterial/2phase_irregularGrid.json b/python/tests/resources/ConfigMaterial/2phase_irregularGrid.json similarity index 100% rename from python/tests/reference/ConfigMaterial/2phase_irregularGrid.json rename to python/tests/resources/ConfigMaterial/2phase_irregularGrid.json diff --git a/python/tests/reference/ConfigMaterial/2phase_irregularGrid.xdmf b/python/tests/resources/ConfigMaterial/2phase_irregularGrid.xdmf similarity index 100% rename from python/tests/reference/ConfigMaterial/2phase_irregularGrid.xdmf rename to python/tests/resources/ConfigMaterial/2phase_irregularGrid.xdmf diff --git a/python/tests/reference/ConfigMaterial/material.yaml b/python/tests/resources/ConfigMaterial/material.yaml similarity index 100% rename from python/tests/reference/ConfigMaterial/material.yaml rename to python/tests/resources/ConfigMaterial/material.yaml diff --git a/python/tests/reference/ConfigMaterial/measured.dream3d b/python/tests/resources/ConfigMaterial/measured.dream3d similarity index 100% rename from python/tests/reference/ConfigMaterial/measured.dream3d rename to python/tests/resources/ConfigMaterial/measured.dream3d diff --git a/python/tests/reference/ConfigMaterial/measured.material.yaml b/python/tests/resources/ConfigMaterial/measured.material.yaml similarity index 100% rename from python/tests/reference/ConfigMaterial/measured.material.yaml rename to python/tests/resources/ConfigMaterial/measured.material.yaml diff --git a/python/tests/reference/ConfigMaterial/measured.xdmf b/python/tests/resources/ConfigMaterial/measured.xdmf similarity index 100% rename from python/tests/reference/ConfigMaterial/measured.xdmf rename to python/tests/resources/ConfigMaterial/measured.xdmf diff --git a/python/tests/resources/Grid/.gitattributes b/python/tests/resources/Grid/.gitattributes new file mode 100644 index 000000000..c0166b217 --- /dev/null +++ b/python/tests/resources/Grid/.gitattributes @@ -0,0 +1 @@ +n10-id1_scaled.vtk binary diff --git a/python/tests/reference/Grid/2phase_irregularGrid.dream3d b/python/tests/resources/Grid/2phase_irregularGrid.dream3d similarity index 100% rename from python/tests/reference/Grid/2phase_irregularGrid.dream3d rename to python/tests/resources/Grid/2phase_irregularGrid.dream3d diff --git a/python/tests/reference/Grid/2phase_irregularGrid.json b/python/tests/resources/Grid/2phase_irregularGrid.json similarity index 100% rename from python/tests/reference/Grid/2phase_irregularGrid.json rename to python/tests/resources/Grid/2phase_irregularGrid.json diff --git a/python/tests/reference/Grid/2phase_irregularGrid.xdmf b/python/tests/resources/Grid/2phase_irregularGrid.xdmf similarity index 100% rename from python/tests/reference/Grid/2phase_irregularGrid.xdmf rename to python/tests/resources/Grid/2phase_irregularGrid.xdmf diff --git a/python/tests/reference/Grid/clean_1.0_1+2+3_False.vti b/python/tests/resources/Grid/clean_1.0_1+2+3_False.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.0_1+2+3_False.vti rename to python/tests/resources/Grid/clean_1.0_1+2+3_False.vti diff --git a/python/tests/reference/Grid/clean_1.0_1+2+3_True.vti b/python/tests/resources/Grid/clean_1.0_1+2+3_True.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.0_1+2+3_True.vti rename to python/tests/resources/Grid/clean_1.0_1+2+3_True.vti diff --git a/python/tests/reference/Grid/clean_1.0_1_False.vti b/python/tests/resources/Grid/clean_1.0_1_False.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.0_1_False.vti rename to python/tests/resources/Grid/clean_1.0_1_False.vti diff --git a/python/tests/reference/Grid/clean_1.0_1_True.vti b/python/tests/resources/Grid/clean_1.0_1_True.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.0_1_True.vti rename to python/tests/resources/Grid/clean_1.0_1_True.vti diff --git a/python/tests/reference/Grid/clean_1.0_None_False.vti b/python/tests/resources/Grid/clean_1.0_None_False.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.0_None_False.vti rename to python/tests/resources/Grid/clean_1.0_None_False.vti diff --git a/python/tests/reference/Grid/clean_1.0_None_True.vti b/python/tests/resources/Grid/clean_1.0_None_True.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.0_None_True.vti rename to python/tests/resources/Grid/clean_1.0_None_True.vti diff --git a/python/tests/reference/Grid/clean_1.7320508075688772_1+2+3_False.vti b/python/tests/resources/Grid/clean_1.7320508075688772_1+2+3_False.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.7320508075688772_1+2+3_False.vti rename to python/tests/resources/Grid/clean_1.7320508075688772_1+2+3_False.vti diff --git a/python/tests/reference/Grid/clean_1.7320508075688772_1+2+3_True.vti b/python/tests/resources/Grid/clean_1.7320508075688772_1+2+3_True.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.7320508075688772_1+2+3_True.vti rename to python/tests/resources/Grid/clean_1.7320508075688772_1+2+3_True.vti diff --git a/python/tests/reference/Grid/clean_1.7320508075688772_1_False.vti b/python/tests/resources/Grid/clean_1.7320508075688772_1_False.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.7320508075688772_1_False.vti rename to python/tests/resources/Grid/clean_1.7320508075688772_1_False.vti diff --git a/python/tests/reference/Grid/clean_1.7320508075688772_1_True.vti b/python/tests/resources/Grid/clean_1.7320508075688772_1_True.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.7320508075688772_1_True.vti rename to python/tests/resources/Grid/clean_1.7320508075688772_1_True.vti diff --git a/python/tests/reference/Grid/clean_1.7320508075688772_None_False.vti b/python/tests/resources/Grid/clean_1.7320508075688772_None_False.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.7320508075688772_None_False.vti rename to python/tests/resources/Grid/clean_1.7320508075688772_None_False.vti diff --git a/python/tests/reference/Grid/clean_1.7320508075688772_None_True.vti b/python/tests/resources/Grid/clean_1.7320508075688772_None_True.vti similarity index 100% rename from python/tests/reference/Grid/clean_1.7320508075688772_None_True.vti rename to python/tests/resources/Grid/clean_1.7320508075688772_None_True.vti diff --git a/python/tests/reference/Grid/flip_directions_x-y-z.vti b/python/tests/resources/Grid/flip_directions_x-y-z.vti similarity index 100% rename from python/tests/reference/Grid/flip_directions_x-y-z.vti rename to python/tests/resources/Grid/flip_directions_x-y-z.vti diff --git a/python/tests/reference/Grid/flip_directions_x.vti b/python/tests/resources/Grid/flip_directions_x.vti similarity index 100% rename from python/tests/reference/Grid/flip_directions_x.vti rename to python/tests/resources/Grid/flip_directions_x.vti diff --git a/python/tests/reference/Grid/flip_directions_y-z.vti b/python/tests/resources/Grid/flip_directions_y-z.vti similarity index 100% rename from python/tests/reference/Grid/flip_directions_y-z.vti rename to python/tests/resources/Grid/flip_directions_y-z.vti diff --git a/python/tests/reference/Grid/flip_directions_z-x-y.vti b/python/tests/resources/Grid/flip_directions_z-x-y.vti similarity index 100% rename from python/tests/reference/Grid/flip_directions_z-x-y.vti rename to python/tests/resources/Grid/flip_directions_z-x-y.vti diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20.vti b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20.vti similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20.vti rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20.vti diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_x_False.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_x_False.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_x_False.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_x_False.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_x_True.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_x_True.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_x_True.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_x_True.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xy_False.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xy_False.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xy_False.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xy_False.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xy_True.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xy_True.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xy_True.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xy_True.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xyz_False.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xyz_False.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xyz_False.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xyz_False.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xyz_True.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xyz_True.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xyz_True.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xyz_True.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xz_False.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xz_False.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xz_False.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xz_False.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xz_True.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xz_True.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_xz_True.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_xz_True.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_y_False.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_y_False.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_y_False.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_y_False.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_y_True.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_y_True.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_y_True.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_y_True.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_z_False.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_z_False.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_z_False.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_z_False.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_z_True.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_z_True.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_z_True.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_z_True.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_zy_False.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_zy_False.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_zy_False.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_zy_False.vtu diff --git a/python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_zy_True.vtu b/python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_zy_True.vtu similarity index 100% rename from python/tests/reference/Grid/get_grain_boundaries_8g12x15x20_zy_True.vtu rename to python/tests/resources/Grid/get_grain_boundaries_8g12x15x20_zy_True.vtu diff --git a/python/tests/reference/Grid/measured.dream3d b/python/tests/resources/Grid/measured.dream3d similarity index 100% rename from python/tests/reference/Grid/measured.dream3d rename to python/tests/resources/Grid/measured.dream3d diff --git a/python/tests/reference/Grid/measured.vti b/python/tests/resources/Grid/measured.vti similarity index 100% rename from python/tests/reference/Grid/measured.vti rename to python/tests/resources/Grid/measured.vti diff --git a/python/tests/reference/Grid/measured.xdmf b/python/tests/resources/Grid/measured.xdmf similarity index 100% rename from python/tests/reference/Grid/measured.xdmf rename to python/tests/resources/Grid/measured.xdmf diff --git a/python/tests/reference/Grid/mirror_directions_x+reflect_False.vti b/python/tests/resources/Grid/mirror_directions_x+reflect_False.vti similarity index 100% rename from python/tests/reference/Grid/mirror_directions_x+reflect_False.vti rename to python/tests/resources/Grid/mirror_directions_x+reflect_False.vti diff --git a/python/tests/reference/Grid/mirror_directions_x-y-z+reflect_True.vti b/python/tests/resources/Grid/mirror_directions_x-y-z+reflect_True.vti similarity index 100% rename from python/tests/reference/Grid/mirror_directions_x-y-z+reflect_True.vti rename to python/tests/resources/Grid/mirror_directions_x-y-z+reflect_True.vti diff --git a/python/tests/reference/Grid/mirror_directions_y-z+reflect_False.vti b/python/tests/resources/Grid/mirror_directions_y-z+reflect_False.vti similarity index 100% rename from python/tests/reference/Grid/mirror_directions_y-z+reflect_False.vti rename to python/tests/resources/Grid/mirror_directions_y-z+reflect_False.vti diff --git a/python/tests/reference/Grid/mirror_directions_z-x-y+reflect_False.vti b/python/tests/resources/Grid/mirror_directions_z-x-y+reflect_False.vti similarity index 100% rename from python/tests/reference/Grid/mirror_directions_z-x-y+reflect_False.vti rename to python/tests/resources/Grid/mirror_directions_z-x-y+reflect_False.vti diff --git a/python/tests/reference/Grid/n10-id1_scaled.vti b/python/tests/resources/Grid/n10-id1_scaled.vti similarity index 100% rename from python/tests/reference/Grid/n10-id1_scaled.vti rename to python/tests/resources/Grid/n10-id1_scaled.vti diff --git a/python/tests/reference/Grid/n10-id1_scaled.vtk b/python/tests/resources/Grid/n10-id1_scaled.vtk similarity index 100% rename from python/tests/reference/Grid/n10-id1_scaled.vtk rename to python/tests/resources/Grid/n10-id1_scaled.vtk diff --git a/python/tests/reference/Grid/rotate_Eulers_0.0-32.0-240.0.vti b/python/tests/resources/Grid/rotate_Eulers_0.0-32.0-240.0.vti similarity index 100% rename from python/tests/reference/Grid/rotate_Eulers_0.0-32.0-240.0.vti rename to python/tests/resources/Grid/rotate_Eulers_0.0-32.0-240.0.vti diff --git a/python/tests/reference/Grid/rotate_Eulers_32.0-68.0-21.0.vti b/python/tests/resources/Grid/rotate_Eulers_32.0-68.0-21.0.vti similarity index 100% rename from python/tests/reference/Grid/rotate_Eulers_32.0-68.0-21.0.vti rename to python/tests/resources/Grid/rotate_Eulers_32.0-68.0-21.0.vti diff --git a/python/tests/reference/Grid/scale_grid_10-10-10.vti b/python/tests/resources/Grid/scale_grid_10-10-10.vti similarity index 100% rename from python/tests/reference/Grid/scale_grid_10-10-10.vti rename to python/tests/resources/Grid/scale_grid_10-10-10.vti diff --git a/python/tests/reference/Grid/scale_grid_10-11-10.vti b/python/tests/resources/Grid/scale_grid_10-11-10.vti similarity index 100% rename from python/tests/reference/Grid/scale_grid_10-11-10.vti rename to python/tests/resources/Grid/scale_grid_10-11-10.vti diff --git a/python/tests/reference/Grid/scale_grid_10-13-10.vti b/python/tests/resources/Grid/scale_grid_10-13-10.vti similarity index 100% rename from python/tests/reference/Grid/scale_grid_10-13-10.vti rename to python/tests/resources/Grid/scale_grid_10-13-10.vti diff --git a/python/tests/reference/Grid/scale_grid_10-20-2.vti b/python/tests/resources/Grid/scale_grid_10-20-2.vti similarity index 100% rename from python/tests/reference/Grid/scale_grid_10-20-2.vti rename to python/tests/resources/Grid/scale_grid_10-20-2.vti diff --git a/python/tests/reference/Grid/scale_grid_5-4-20.vti b/python/tests/resources/Grid/scale_grid_5-4-20.vti similarity index 100% rename from python/tests/reference/Grid/scale_grid_5-4-20.vti rename to python/tests/resources/Grid/scale_grid_5-4-20.vti diff --git a/python/tests/reference/Grid/scale_grid_8-10-12.vti b/python/tests/resources/Grid/scale_grid_8-10-12.vti similarity index 100% rename from python/tests/reference/Grid/scale_grid_8-10-12.vti rename to python/tests/resources/Grid/scale_grid_8-10-12.vti diff --git a/python/tests/reference/Orientation/cF_Bain.txt b/python/tests/resources/Orientation/cF_Bain.txt similarity index 100% rename from python/tests/reference/Orientation/cF_Bain.txt rename to python/tests/resources/Orientation/cF_Bain.txt diff --git a/python/tests/reference/Orientation/cF_GT.txt b/python/tests/resources/Orientation/cF_GT.txt similarity index 100% rename from python/tests/reference/Orientation/cF_GT.txt rename to python/tests/resources/Orientation/cF_GT.txt diff --git a/python/tests/reference/Orientation/cF_GT_prime.txt b/python/tests/resources/Orientation/cF_GT_prime.txt similarity index 100% rename from python/tests/reference/Orientation/cF_GT_prime.txt rename to python/tests/resources/Orientation/cF_GT_prime.txt diff --git a/python/tests/reference/Orientation/cF_KS.txt b/python/tests/resources/Orientation/cF_KS.txt similarity index 100% rename from python/tests/reference/Orientation/cF_KS.txt rename to python/tests/resources/Orientation/cF_KS.txt diff --git a/python/tests/reference/Orientation/cF_NW.txt b/python/tests/resources/Orientation/cF_NW.txt similarity index 100% rename from python/tests/reference/Orientation/cF_NW.txt rename to python/tests/resources/Orientation/cF_NW.txt diff --git a/python/tests/reference/Orientation/cF_Pitsch.txt b/python/tests/resources/Orientation/cF_Pitsch.txt similarity index 100% rename from python/tests/reference/Orientation/cF_Pitsch.txt rename to python/tests/resources/Orientation/cF_Pitsch.txt diff --git a/python/tests/reference/Orientation/cF_slip.txt b/python/tests/resources/Orientation/cF_slip.txt similarity index 100% rename from python/tests/reference/Orientation/cF_slip.txt rename to python/tests/resources/Orientation/cF_slip.txt diff --git a/python/tests/reference/Orientation/cF_twin.txt b/python/tests/resources/Orientation/cF_twin.txt similarity index 100% rename from python/tests/reference/Orientation/cF_twin.txt rename to python/tests/resources/Orientation/cF_twin.txt diff --git a/python/tests/reference/Orientation/cI_Bain.txt b/python/tests/resources/Orientation/cI_Bain.txt similarity index 100% rename from python/tests/reference/Orientation/cI_Bain.txt rename to python/tests/resources/Orientation/cI_Bain.txt diff --git a/python/tests/reference/Orientation/cI_GT.txt b/python/tests/resources/Orientation/cI_GT.txt similarity index 100% rename from python/tests/reference/Orientation/cI_GT.txt rename to python/tests/resources/Orientation/cI_GT.txt diff --git a/python/tests/reference/Orientation/cI_GT_prime.txt b/python/tests/resources/Orientation/cI_GT_prime.txt similarity index 100% rename from python/tests/reference/Orientation/cI_GT_prime.txt rename to python/tests/resources/Orientation/cI_GT_prime.txt diff --git a/python/tests/reference/Orientation/cI_KS.txt b/python/tests/resources/Orientation/cI_KS.txt similarity index 100% rename from python/tests/reference/Orientation/cI_KS.txt rename to python/tests/resources/Orientation/cI_KS.txt diff --git a/python/tests/reference/Orientation/cI_NW.txt b/python/tests/resources/Orientation/cI_NW.txt similarity index 100% rename from python/tests/reference/Orientation/cI_NW.txt rename to python/tests/resources/Orientation/cI_NW.txt diff --git a/python/tests/reference/Orientation/cI_Pitsch.txt b/python/tests/resources/Orientation/cI_Pitsch.txt similarity index 100% rename from python/tests/reference/Orientation/cI_Pitsch.txt rename to python/tests/resources/Orientation/cI_Pitsch.txt diff --git a/python/tests/reference/Orientation/cI_slip.txt b/python/tests/resources/Orientation/cI_slip.txt similarity index 100% rename from python/tests/reference/Orientation/cI_slip.txt rename to python/tests/resources/Orientation/cI_slip.txt diff --git a/python/tests/reference/Orientation/cI_twin.txt b/python/tests/resources/Orientation/cI_twin.txt similarity index 100% rename from python/tests/reference/Orientation/cI_twin.txt rename to python/tests/resources/Orientation/cI_twin.txt diff --git a/python/tests/reference/Orientation/hP_slip.txt b/python/tests/resources/Orientation/hP_slip.txt similarity index 100% rename from python/tests/reference/Orientation/hP_slip.txt rename to python/tests/resources/Orientation/hP_slip.txt diff --git a/python/tests/reference/Orientation/hP_twin.txt b/python/tests/resources/Orientation/hP_twin.txt similarity index 100% rename from python/tests/reference/Orientation/hP_twin.txt rename to python/tests/resources/Orientation/hP_twin.txt diff --git a/python/tests/reference/Orientation/unitcell_cubic_0_0_0.pdf b/python/tests/resources/Orientation/unitcell_cubic_0_0_0.pdf similarity index 100% rename from python/tests/reference/Orientation/unitcell_cubic_0_0_0.pdf rename to python/tests/resources/Orientation/unitcell_cubic_0_0_0.pdf diff --git a/python/tests/reference/Orientation/unitcell_cubic_0_45_0.pdf b/python/tests/resources/Orientation/unitcell_cubic_0_45_0.pdf similarity index 100% rename from python/tests/reference/Orientation/unitcell_cubic_0_45_0.pdf rename to python/tests/resources/Orientation/unitcell_cubic_0_45_0.pdf diff --git a/python/tests/reference/Orientation/unitcell_cubic_180_45_180.pdf b/python/tests/resources/Orientation/unitcell_cubic_180_45_180.pdf similarity index 100% rename from python/tests/reference/Orientation/unitcell_cubic_180_45_180.pdf rename to python/tests/resources/Orientation/unitcell_cubic_180_45_180.pdf diff --git a/python/tests/reference/Orientation/unitcell_cubic_45_0_0.pdf b/python/tests/resources/Orientation/unitcell_cubic_45_0_0.pdf similarity index 100% rename from python/tests/reference/Orientation/unitcell_cubic_45_0_0.pdf rename to python/tests/resources/Orientation/unitcell_cubic_45_0_0.pdf diff --git a/python/tests/reference/Orientation/unitcell_cubic_90_45_270.pdf b/python/tests/resources/Orientation/unitcell_cubic_90_45_270.pdf similarity index 100% rename from python/tests/reference/Orientation/unitcell_cubic_90_45_270.pdf rename to python/tests/resources/Orientation/unitcell_cubic_90_45_270.pdf diff --git a/python/tests/reference/Result/12grains6x7x8.material.yaml b/python/tests/resources/Result/12grains6x7x8.material.yaml similarity index 100% rename from python/tests/reference/Result/12grains6x7x8.material.yaml rename to python/tests/resources/Result/12grains6x7x8.material.yaml diff --git a/python/tests/reference/Result/12grains6x7x8.vti b/python/tests/resources/Result/12grains6x7x8.vti similarity index 100% rename from python/tests/reference/Result/12grains6x7x8.vti rename to python/tests/resources/Result/12grains6x7x8.vti diff --git a/python/tests/resources/Result/12grains6x7x8_tensionY.hdf5 b/python/tests/resources/Result/12grains6x7x8_tensionY.hdf5 new file mode 100644 index 000000000..84e5bb73e Binary files /dev/null and b/python/tests/resources/Result/12grains6x7x8_tensionY.hdf5 differ diff --git a/python/tests/reference/Result/4grains2x4x3.material.yaml b/python/tests/resources/Result/4grains2x4x3.material.yaml similarity index 100% rename from python/tests/reference/Result/4grains2x4x3.material.yaml rename to python/tests/resources/Result/4grains2x4x3.material.yaml diff --git a/python/tests/reference/Result/4grains2x4x3.vti b/python/tests/resources/Result/4grains2x4x3.vti similarity index 100% rename from python/tests/reference/Result/4grains2x4x3.vti rename to python/tests/resources/Result/4grains2x4x3.vti diff --git a/python/tests/reference/Result/4grains2x4x3_compressionY.hdf5 b/python/tests/resources/Result/4grains2x4x3_compressionY.hdf5 similarity index 58% rename from python/tests/reference/Result/4grains2x4x3_compressionY.hdf5 rename to python/tests/resources/Result/4grains2x4x3_compressionY.hdf5 index 2d1d0ee33..041feca39 100644 Binary files a/python/tests/reference/Result/4grains2x4x3_compressionY.hdf5 and b/python/tests/resources/Result/4grains2x4x3_compressionY.hdf5 differ diff --git a/python/tests/reference/Result/6grains6x7x8_single_phase.material.yaml b/python/tests/resources/Result/6grains6x7x8_single_phase.material.yaml similarity index 100% rename from python/tests/reference/Result/6grains6x7x8_single_phase.material.yaml rename to python/tests/resources/Result/6grains6x7x8_single_phase.material.yaml diff --git a/python/tests/reference/Result/6grains6x7x8_single_phase.vti b/python/tests/resources/Result/6grains6x7x8_single_phase.vti similarity index 100% rename from python/tests/reference/Result/6grains6x7x8_single_phase.vti rename to python/tests/resources/Result/6grains6x7x8_single_phase.vti diff --git a/python/tests/resources/Result/6grains6x7x8_single_phase_tensionY.hdf5 b/python/tests/resources/Result/6grains6x7x8_single_phase_tensionY.hdf5 new file mode 100644 index 000000000..eb3f73ea4 Binary files /dev/null and b/python/tests/resources/Result/6grains6x7x8_single_phase_tensionY.hdf5 differ diff --git a/python/tests/reference/Result/6grains6x7x8_single_phase_tensionY.xdmf b/python/tests/resources/Result/6grains6x7x8_single_phase_tensionY.xdmf similarity index 99% rename from python/tests/reference/Result/6grains6x7x8_single_phase_tensionY.xdmf rename to python/tests/resources/Result/6grains6x7x8_single_phase_tensionY.xdmf index cc92cd571..80b96fecb 100644 --- a/python/tests/reference/Result/6grains6x7x8_single_phase_tensionY.xdmf +++ b/python/tests/resources/Result/6grains6x7x8_single_phase_tensionY.xdmf @@ -26,7 +26,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_0/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_0/phase/pheno_fcc/mechanical/O @@ -177,7 +177,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_4/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_4/phase/pheno_fcc/mechanical/O @@ -328,7 +328,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_8/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_8/phase/pheno_fcc/mechanical/O @@ -479,7 +479,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_12/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_12/phase/pheno_fcc/mechanical/O @@ -630,7 +630,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_16/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_16/phase/pheno_fcc/mechanical/O @@ -781,7 +781,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_20/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_20/phase/pheno_fcc/mechanical/O @@ -932,7 +932,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_24/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_24/phase/pheno_fcc/mechanical/O @@ -1083,7 +1083,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_28/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_28/phase/pheno_fcc/mechanical/O @@ -1234,7 +1234,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_32/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_32/phase/pheno_fcc/mechanical/O @@ -1385,7 +1385,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_36/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_36/phase/pheno_fcc/mechanical/O @@ -1536,7 +1536,7 @@ 6grains6x7x8_single_phase_tensionY.hdf5:increment_40/phase/pheno_fcc/mechanical/L_p - + 6grains6x7x8_single_phase_tensionY.hdf5:increment_40/phase/pheno_fcc/mechanical/O diff --git a/python/tests/resources/Result/check_compile_job1.hdf5 b/python/tests/resources/Result/check_compile_job1.hdf5 new file mode 100644 index 000000000..597598ebf Binary files /dev/null and b/python/tests/resources/Result/check_compile_job1.hdf5 differ diff --git a/python/tests/reference/Result/compressionY.yaml b/python/tests/resources/Result/compressionY.yaml similarity index 100% rename from python/tests/reference/Result/compressionY.yaml rename to python/tests/resources/Result/compressionY.yaml diff --git a/python/tests/reference/Result/export_VTK/test_export_vtk[0-0-0].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-0-0].md5 similarity index 100% rename from python/tests/reference/Result/export_VTK/test_export_vtk[0-0-0].md5 rename to python/tests/resources/Result/export_VTK/test_export_vtk[0-0-0].md5 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-0-1].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-0-1].md5 new file mode 100644 index 000000000..281d96e64 --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-0-1].md5 @@ -0,0 +1 @@ +c7280da4e7cb4d993b9d26d0285cf85e diff --git a/python/tests/reference/Result/export_VTK/test_export_vtk[0-0-2].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-0-2].md5 similarity index 100% rename from python/tests/reference/Result/export_VTK/test_export_vtk[0-0-2].md5 rename to python/tests/resources/Result/export_VTK/test_export_vtk[0-0-2].md5 diff --git a/python/tests/reference/Result/export_VTK/test_export_vtk[0-0-3].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-0-3].md5 similarity index 100% rename from python/tests/reference/Result/export_VTK/test_export_vtk[0-0-3].md5 rename to python/tests/resources/Result/export_VTK/test_export_vtk[0-0-3].md5 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-0].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-0].md5 new file mode 100644 index 000000000..9c015ae9c --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-0].md5 @@ -0,0 +1 @@ +b1d4ed9f72a7a2a261ca4c8c7ce3ecca diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-1].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-1].md5 new file mode 100644 index 000000000..d0e1348fb --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-1].md5 @@ -0,0 +1 @@ +fa58dc50516d0e31c7b84ea06728c477 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-2].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-2].md5 new file mode 100644 index 000000000..37884253d --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-2].md5 @@ -0,0 +1 @@ +db4278b2b1a3cd854595dd62eeef7ac4 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-3].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-3].md5 new file mode 100644 index 000000000..e61abb341 --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-1-3].md5 @@ -0,0 +1 @@ +e8fe1c752a781f31bd5edd79976c58d9 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-0].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-0].md5 new file mode 100644 index 000000000..81e726dd2 --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-0].md5 @@ -0,0 +1 @@ +33475f722f1e39e0952cc121e6e0a59f diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-1].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-1].md5 new file mode 100644 index 000000000..fd43d041e --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-1].md5 @@ -0,0 +1 @@ +72f7ff57a40b26f1f39511259e4dbbfc diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-2].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-2].md5 new file mode 100644 index 000000000..89394e076 --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-2].md5 @@ -0,0 +1 @@ +0861eb141de14a929e4f32aa87bba99f diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-3].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-3].md5 new file mode 100644 index 000000000..01a8edc31 --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[0-2-3].md5 @@ -0,0 +1 @@ +3189b1a625401dc9fd9209e55192cab2 diff --git a/python/tests/reference/Result/export_VTK/test_export_vtk[1-0-0].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-0-0].md5 similarity index 100% rename from python/tests/reference/Result/export_VTK/test_export_vtk[1-0-0].md5 rename to python/tests/resources/Result/export_VTK/test_export_vtk[1-0-0].md5 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-0-1].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-0-1].md5 new file mode 100644 index 000000000..162f7f7ec --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-0-1].md5 @@ -0,0 +1 @@ +53598d0052bf9ddfdf6d755cd375e015 diff --git a/python/tests/reference/Result/export_VTK/test_export_vtk[1-0-2].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-0-2].md5 similarity index 100% rename from python/tests/reference/Result/export_VTK/test_export_vtk[1-0-2].md5 rename to python/tests/resources/Result/export_VTK/test_export_vtk[1-0-2].md5 diff --git a/python/tests/reference/Result/export_VTK/test_export_vtk[1-0-3].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-0-3].md5 similarity index 100% rename from python/tests/reference/Result/export_VTK/test_export_vtk[1-0-3].md5 rename to python/tests/resources/Result/export_VTK/test_export_vtk[1-0-3].md5 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-0].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-0].md5 new file mode 100644 index 000000000..6da5f50e3 --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-0].md5 @@ -0,0 +1 @@ +472e040094eaed7cceb6cdcc82a08e8f diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-1].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-1].md5 new file mode 100644 index 000000000..8c018818b --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-1].md5 @@ -0,0 +1 @@ +83c0accce11142b5b0b6be7ee56c0d5a diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-2].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-2].md5 new file mode 100644 index 000000000..3918fd9f9 --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-2].md5 @@ -0,0 +1 @@ +06de227b18a955cb5b2ea325b4e22fc6 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-3].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-3].md5 new file mode 100644 index 000000000..2dba8e10a --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-1-3].md5 @@ -0,0 +1 @@ +ed793b6089fda37453731d5f820581bd diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-0].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-0].md5 new file mode 100644 index 000000000..f07a3ee2e --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-0].md5 @@ -0,0 +1 @@ +4f85d2613aa70622a2d5f49dc8bf2eb2 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-1].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-1].md5 new file mode 100644 index 000000000..9c0e9da4c --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-1].md5 @@ -0,0 +1 @@ +0aca2c9895589569da20459e64ff58a2 diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-2].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-2].md5 new file mode 100644 index 000000000..af7491c0b --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-2].md5 @@ -0,0 +1 @@ +878d7ae32630ec6651fffe7e1b91048d diff --git a/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-3].md5 b/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-3].md5 new file mode 100644 index 000000000..4581947a3 --- /dev/null +++ b/python/tests/resources/Result/export_VTK/test_export_vtk[1-2-3].md5 @@ -0,0 +1 @@ +9c5b55db21eec2ea0b1c784684b746b6 diff --git a/python/tests/reference/Result/get/test_get[0].pbz2 b/python/tests/resources/Result/get/test_get[0].pbz2 similarity index 100% rename from python/tests/reference/Result/get/test_get[0].pbz2 rename to python/tests/resources/Result/get/test_get[0].pbz2 diff --git a/python/tests/reference/Result/get/test_get[1].pbz2 b/python/tests/resources/Result/get/test_get[1].pbz2 similarity index 100% rename from python/tests/reference/Result/get/test_get[1].pbz2 rename to python/tests/resources/Result/get/test_get[1].pbz2 diff --git a/python/tests/reference/Result/get/test_get[2].pbz2 b/python/tests/resources/Result/get/test_get[2].pbz2 similarity index 100% rename from python/tests/reference/Result/get/test_get[2].pbz2 rename to python/tests/resources/Result/get/test_get[2].pbz2 diff --git a/python/tests/reference/Result/get/test_get[3].pbz2 b/python/tests/resources/Result/get/test_get[3].pbz2 similarity index 100% rename from python/tests/reference/Result/get/test_get[3].pbz2 rename to python/tests/resources/Result/get/test_get[3].pbz2 diff --git a/python/tests/reference/Result/get/test_get[4].pbz2 b/python/tests/resources/Result/get/test_get[4].pbz2 similarity index 100% rename from python/tests/reference/Result/get/test_get[4].pbz2 rename to python/tests/resources/Result/get/test_get[4].pbz2 diff --git a/python/tests/reference/Result/get/test_get[5].pbz2 b/python/tests/resources/Result/get/test_get[5].pbz2 similarity index 100% rename from python/tests/reference/Result/get/test_get[5].pbz2 rename to python/tests/resources/Result/get/test_get[5].pbz2 diff --git a/python/tests/reference/Result/get/test_get[6].pbz2 b/python/tests/resources/Result/get/test_get[6].pbz2 similarity index 100% rename from python/tests/reference/Result/get/test_get[6].pbz2 rename to python/tests/resources/Result/get/test_get[6].pbz2 diff --git a/python/tests/reference/Result/get/test_get[7].pbz2 b/python/tests/resources/Result/get/test_get[7].pbz2 similarity index 100% rename from python/tests/reference/Result/get/test_get[7].pbz2 rename to python/tests/resources/Result/get/test_get[7].pbz2 diff --git a/python/tests/reference/Result/place/test_place[0].pbz2 b/python/tests/resources/Result/place/test_place[0].pbz2 similarity index 100% rename from python/tests/reference/Result/place/test_place[0].pbz2 rename to python/tests/resources/Result/place/test_place[0].pbz2 diff --git a/python/tests/reference/Result/place/test_place[1].pbz2 b/python/tests/resources/Result/place/test_place[1].pbz2 similarity index 100% rename from python/tests/reference/Result/place/test_place[1].pbz2 rename to python/tests/resources/Result/place/test_place[1].pbz2 diff --git a/python/tests/reference/Result/place/test_place[2].pbz2 b/python/tests/resources/Result/place/test_place[2].pbz2 similarity index 100% rename from python/tests/reference/Result/place/test_place[2].pbz2 rename to python/tests/resources/Result/place/test_place[2].pbz2 diff --git a/python/tests/reference/Result/place/test_place[3].pbz2 b/python/tests/resources/Result/place/test_place[3].pbz2 similarity index 100% rename from python/tests/reference/Result/place/test_place[3].pbz2 rename to python/tests/resources/Result/place/test_place[3].pbz2 diff --git a/python/tests/reference/Result/place/test_place[4].pbz2 b/python/tests/resources/Result/place/test_place[4].pbz2 similarity index 100% rename from python/tests/reference/Result/place/test_place[4].pbz2 rename to python/tests/resources/Result/place/test_place[4].pbz2 diff --git a/python/tests/reference/Result/place/test_place[5].pbz2 b/python/tests/resources/Result/place/test_place[5].pbz2 similarity index 100% rename from python/tests/reference/Result/place/test_place[5].pbz2 rename to python/tests/resources/Result/place/test_place[5].pbz2 diff --git a/python/tests/reference/Result/place/test_place[6].pbz2 b/python/tests/resources/Result/place/test_place[6].pbz2 similarity index 100% rename from python/tests/reference/Result/place/test_place[6].pbz2 rename to python/tests/resources/Result/place/test_place[6].pbz2 diff --git a/python/tests/reference/Result/place/test_place[7].pbz2 b/python/tests/resources/Result/place/test_place[7].pbz2 similarity index 100% rename from python/tests/reference/Result/place/test_place[7].pbz2 rename to python/tests/resources/Result/place/test_place[7].pbz2 diff --git a/python/tests/reference/Result/tensionY.yaml b/python/tests/resources/Result/tensionY.yaml similarity index 100% rename from python/tests/reference/Result/tensionY.yaml rename to python/tests/resources/Result/tensionY.yaml diff --git a/python/tests/reference/Result/tensionY_restart.yaml b/python/tests/resources/Result/tensionY_restart.yaml similarity index 100% rename from python/tests/reference/Result/tensionY_restart.yaml rename to python/tests/resources/Result/tensionY_restart.yaml diff --git a/python/tests/reference/Rotation/1_BCC.pdf b/python/tests/resources/Rotation/1_BCC.pdf similarity index 100% rename from python/tests/reference/Rotation/1_BCC.pdf rename to python/tests/resources/Rotation/1_BCC.pdf diff --git a/python/tests/reference/Rotation/1_FCC.pdf b/python/tests/resources/Rotation/1_FCC.pdf similarity index 100% rename from python/tests/reference/Rotation/1_FCC.pdf rename to python/tests/resources/Rotation/1_FCC.pdf diff --git a/python/tests/reference/Rotation/2_BCC.pdf b/python/tests/resources/Rotation/2_BCC.pdf similarity index 100% rename from python/tests/reference/Rotation/2_BCC.pdf rename to python/tests/resources/Rotation/2_BCC.pdf diff --git a/python/tests/reference/Rotation/2_FCC.pdf b/python/tests/resources/Rotation/2_FCC.pdf similarity index 100% rename from python/tests/reference/Rotation/2_FCC.pdf rename to python/tests/resources/Rotation/2_FCC.pdf diff --git a/python/tests/reference/Rotation/ODF_experimental.odf b/python/tests/resources/Rotation/ODF_experimental.odf similarity index 100% rename from python/tests/reference/Rotation/ODF_experimental.odf rename to python/tests/resources/Rotation/ODF_experimental.odf diff --git a/python/tests/reference/Rotation/ODF_experimental.txt b/python/tests/resources/Rotation/ODF_experimental.txt similarity index 100% rename from python/tests/reference/Rotation/ODF_experimental.txt rename to python/tests/resources/Rotation/ODF_experimental.txt diff --git a/python/tests/reference/Rotation/ODF_experimental_cell.txt b/python/tests/resources/Rotation/ODF_experimental_cell.txt similarity index 100% rename from python/tests/reference/Rotation/ODF_experimental_cell.txt rename to python/tests/resources/Rotation/ODF_experimental_cell.txt diff --git a/python/tests/reference/Rotation/PoleFigures_OR.m b/python/tests/resources/Rotation/PoleFigures_OR.m similarity index 100% rename from python/tests/reference/Rotation/PoleFigures_OR.m rename to python/tests/resources/Rotation/PoleFigures_OR.m diff --git a/python/tests/reference/Rotation/Visualize_hybridIA_sampling.ipynb b/python/tests/resources/Rotation/Visualize_hybridIA_sampling.ipynb similarity index 100% rename from python/tests/reference/Rotation/Visualize_hybridIA_sampling.ipynb rename to python/tests/resources/Rotation/Visualize_hybridIA_sampling.ipynb diff --git a/python/tests/reference/Rotation/bcc_Bain.txt b/python/tests/resources/Rotation/bcc_Bain.txt similarity index 100% rename from python/tests/reference/Rotation/bcc_Bain.txt rename to python/tests/resources/Rotation/bcc_Bain.txt diff --git a/python/tests/reference/Rotation/bcc_GT.txt b/python/tests/resources/Rotation/bcc_GT.txt similarity index 100% rename from python/tests/reference/Rotation/bcc_GT.txt rename to python/tests/resources/Rotation/bcc_GT.txt diff --git a/python/tests/reference/Rotation/bcc_GT_prime.txt b/python/tests/resources/Rotation/bcc_GT_prime.txt similarity index 100% rename from python/tests/reference/Rotation/bcc_GT_prime.txt rename to python/tests/resources/Rotation/bcc_GT_prime.txt diff --git a/python/tests/reference/Rotation/bcc_KS.txt b/python/tests/resources/Rotation/bcc_KS.txt similarity index 100% rename from python/tests/reference/Rotation/bcc_KS.txt rename to python/tests/resources/Rotation/bcc_KS.txt diff --git a/python/tests/reference/Rotation/bcc_NW.txt b/python/tests/resources/Rotation/bcc_NW.txt similarity index 100% rename from python/tests/reference/Rotation/bcc_NW.txt rename to python/tests/resources/Rotation/bcc_NW.txt diff --git a/python/tests/reference/Rotation/bcc_Pitsch.txt b/python/tests/resources/Rotation/bcc_Pitsch.txt similarity index 100% rename from python/tests/reference/Rotation/bcc_Pitsch.txt rename to python/tests/resources/Rotation/bcc_Pitsch.txt diff --git a/python/tests/reference/Rotation/fcc_Bain.txt b/python/tests/resources/Rotation/fcc_Bain.txt similarity index 100% rename from python/tests/reference/Rotation/fcc_Bain.txt rename to python/tests/resources/Rotation/fcc_Bain.txt diff --git a/python/tests/reference/Rotation/fcc_GT.txt b/python/tests/resources/Rotation/fcc_GT.txt similarity index 100% rename from python/tests/reference/Rotation/fcc_GT.txt rename to python/tests/resources/Rotation/fcc_GT.txt diff --git a/python/tests/reference/Rotation/fcc_GT_prime.txt b/python/tests/resources/Rotation/fcc_GT_prime.txt similarity index 100% rename from python/tests/reference/Rotation/fcc_GT_prime.txt rename to python/tests/resources/Rotation/fcc_GT_prime.txt diff --git a/python/tests/reference/Rotation/fcc_KS.txt b/python/tests/resources/Rotation/fcc_KS.txt similarity index 100% rename from python/tests/reference/Rotation/fcc_KS.txt rename to python/tests/resources/Rotation/fcc_KS.txt diff --git a/python/tests/reference/Rotation/fcc_NW.txt b/python/tests/resources/Rotation/fcc_NW.txt similarity index 100% rename from python/tests/reference/Rotation/fcc_NW.txt rename to python/tests/resources/Rotation/fcc_NW.txt diff --git a/python/tests/reference/Rotation/fcc_Pitsch.txt b/python/tests/resources/Rotation/fcc_Pitsch.txt similarity index 100% rename from python/tests/reference/Rotation/fcc_Pitsch.txt rename to python/tests/resources/Rotation/fcc_Pitsch.txt diff --git a/python/tests/reference/Table/datatype-mix.txt b/python/tests/resources/Table/datatype-mix.txt similarity index 100% rename from python/tests/reference/Table/datatype-mix.txt rename to python/tests/resources/Table/datatype-mix.txt diff --git a/python/tests/reference/Table/simple.ang b/python/tests/resources/Table/simple.ang similarity index 100% rename from python/tests/reference/Table/simple.ang rename to python/tests/resources/Table/simple.ang diff --git a/python/tests/reference/Table/whitespace-mix.txt b/python/tests/resources/Table/whitespace-mix.txt similarity index 100% rename from python/tests/reference/Table/whitespace-mix.txt rename to python/tests/resources/Table/whitespace-mix.txt diff --git a/python/tests/reference/VTK/polyData.vtp b/python/tests/resources/VTK/polyData.vtp similarity index 100% rename from python/tests/reference/VTK/polyData.vtp rename to python/tests/resources/VTK/polyData.vtp diff --git a/python/tests/reference/VTK/rectilinearGrid.vtr b/python/tests/resources/VTK/rectilinearGrid.vtr similarity index 100% rename from python/tests/reference/VTK/rectilinearGrid.vtr rename to python/tests/resources/VTK/rectilinearGrid.vtr diff --git a/python/tests/test_Colormap.py b/python/tests/test_Colormap.py index 12a26e550..7e1d2e9b5 100644 --- a/python/tests/test_Colormap.py +++ b/python/tests/test_Colormap.py @@ -10,9 +10,9 @@ from PIL import ImageChops from damask import Colormap @pytest.fixture -def ref_path(ref_path_base): - """Directory containing reference results.""" - return ref_path_base/'Colormap' +def res_path(res_path_base): + """Directory containing testing resources.""" + return res_path_base/'Colormap' class TestColormap: @@ -156,13 +156,13 @@ class TestColormap: rtol=0.005) @pytest.mark.parametrize('bounds',[None,[2,10]]) - def test_shade(self,ref_path,update,bounds): + def test_shade(self,res_path,update,bounds): data = np.add(*np.indices((10, 11))) img_current = Colormap.from_predefined('orientation').shade(data,bounds=bounds) if update: - img_current.save(ref_path/f'shade_{bounds}.png') + img_current.save(res_path/f'shade_{bounds}.png') else: - img_reference = Image.open(ref_path/f'shade_{bounds}.png') + img_reference = Image.open(res_path/f'shade_{bounds}.png') diff = ImageChops.difference(img_reference.convert('RGB'),img_current.convert('RGB')) assert not diff.getbbox() @@ -174,14 +174,14 @@ class TestColormap: ('GOM','.legend'), ('gmsh','.msh') ]) - def test_compare_reference(self,format,ext,tmp_path,ref_path,update): + def test_compare_reference(self,format,ext,tmp_path,res_path,update): name = 'binary' c = Colormap.from_predefined(name) # noqa if update: - os.chdir(ref_path) + os.chdir(res_path) eval(f'c.save_{format}()') else: os.chdir(tmp_path) eval(f'c.save_{format}()') time.sleep(.5) - assert filecmp.cmp(tmp_path/(name+ext),ref_path/(name+ext)) + assert filecmp.cmp(tmp_path/(name+ext),res_path/(name+ext)) diff --git a/python/tests/test_Config.py b/python/tests/test_Config.py index 0fce31106..ebf5ec9a8 100644 --- a/python/tests/test_Config.py +++ b/python/tests/test_Config.py @@ -7,6 +7,17 @@ from damask import Orientation class TestConfig: + def test_init_keyword(self): + assert Config(p=4)['p'] == 4 + + @pytest.mark.parametrize('config',[{'p':1},'{p: 1}']) + def test_init_config(self,config): + assert Config(config)['p'] == 1 + + @pytest.mark.parametrize('config',[{'p':1},'{p: 1}']) + def test_init_both(self,config): + assert Config(config,p=2)['p'] == 2 + @pytest.mark.parametrize('flow_style',[None,True,False]) def test_load_save_str(self,tmp_path,flow_style): config = Config() @@ -36,7 +47,6 @@ class TestConfig: assert (config | Config(dummy)).delete({ 'hello':1,'foo':2 }) == config assert (config | Config(dummy)).delete(Config({'hello':1 })) == config | {'foo':'bar'} - def test_repr(self,tmp_path): config = Config() config['A'] = 1 diff --git a/python/tests/test_ConfigMaterial.py b/python/tests/test_ConfigMaterial.py index a9cf9089d..b350356a8 100644 --- a/python/tests/test_ConfigMaterial.py +++ b/python/tests/test_ConfigMaterial.py @@ -9,16 +9,37 @@ from damask import Rotation from damask import Grid @pytest.fixture -def ref_path(ref_path_base): - """Directory containing reference results.""" - return ref_path_base/'ConfigMaterial' +def res_path(res_path_base): + """Directory containing testing resources.""" + return res_path_base/'ConfigMaterial' class TestConfigMaterial: + def test_init_empty(self): + c = ConfigMaterial() + assert len(c) == 3 + assert c['homogenization'] == {} + assert c['phase'] == {} + assert c['material'] == [] + + def test_init_d(self): + c = ConfigMaterial(config={'phase':4}) + assert len(c) == 1 + assert c['phase'] == 4 + + @pytest.mark.parametrize('kwargs',[{'homogenization':{'SX':{}}}, + {'phase':{'Aluminum':{}}}, + {'material':[{'A':1},{'B':2}]}]) + def test_init_some(self,kwargs): + c = ConfigMaterial(**kwargs) + assert len(c) == 3 + for k,v in kwargs.items(): + if k in kwargs: assert v == kwargs[k] + @pytest.mark.parametrize('fname',[None,'test.yaml']) - def test_load_save(self,ref_path,tmp_path,fname): - reference = ConfigMaterial.load(ref_path/'material.yaml') + def test_load_save(self,res_path,tmp_path,fname): + reference = ConfigMaterial.load(res_path/'material.yaml') os.chdir(tmp_path) if fname is None: reference.save() @@ -28,78 +49,78 @@ class TestConfigMaterial: new = ConfigMaterial.load(fname) assert reference == new - def test_valid_complete(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_valid_complete(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') assert material_config.is_valid and material_config.is_complete - def test_invalid_lattice(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_invalid_lattice(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') material_config['phase']['Aluminum']['lattice']='fxc' assert not material_config.is_valid - def test_invalid_orientation(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_invalid_orientation(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') material_config['material'][0]['constituents'][0]['O']=[0,0,0,0] assert not material_config.is_valid @pytest.mark.xfail(sys.platform == 'win32', reason='utf8 "not equal" might cause trouble') - def test_invalid_fraction(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_invalid_fraction(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') material_config['material'][0]['constituents'][0]['v']=.9 assert not material_config.is_valid @pytest.mark.parametrize('item',['homogenization','phase','material']) - def test_incomplete_missing(self,ref_path,item): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_incomplete_missing(self,res_path,item): + material_config = ConfigMaterial.load(res_path/'material.yaml') del material_config[item] assert not material_config.is_complete @pytest.mark.parametrize('item',['O','phase']) - def test_incomplete_material_constituent(self,ref_path,item): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_incomplete_material_constituent(self,res_path,item): + material_config = ConfigMaterial.load(res_path/'material.yaml') del material_config['material'][0]['constituents'][0][item] assert not material_config.is_complete - def test_incomplete_material_homogenization(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_incomplete_material_homogenization(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') del material_config['material'][0]['homogenization'] assert not material_config.is_complete - def test_incomplete_wrong_phase(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_incomplete_wrong_phase(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') new = material_config.material_rename_phase({'Steel':'FeNbC'}) assert not new.is_complete - def test_incomplete_wrong_homogenization(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_incomplete_wrong_homogenization(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') new = material_config.material_rename_homogenization({'Taylor':'isostrain'}) assert not new.is_complete - def test_empty_phase(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_empty_phase(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') material_config['phase'] = None assert not material_config.is_complete - def test_empty_homogenization(self,ref_path): - material_config = ConfigMaterial.load(ref_path/'material.yaml') + def test_empty_homogenization(self,res_path): + material_config = ConfigMaterial.load(res_path/'material.yaml') material_config['homogenization'] = None assert not material_config.is_complete def test_from_table(self): N = np.random.randint(3,10) a = np.vstack((np.hstack((np.arange(N),np.arange(N)[::-1])), - np.ones(N*2),np.zeros(N*2),np.ones(N*2),np.ones(N*2), + np.zeros(N*2),np.ones(N*2),np.zeros(N*2),np.zeros(N*2), np.ones(N*2), )).T t = Table({'varying':1,'constant':4,'ones':1},a) c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':'ones'}) assert len(c['material']) == N for i,m in enumerate(c['material']): - assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [1,0,1,1]).all() + assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [0,1,0,0]).all() - def test_updated_dicts(self,ref_path): + def test_updated_dicts(self,res_path): m1 = ConfigMaterial().material_add(phase=['Aluminum'],O=[1.0,0.0,0.0,0.0],homogenization='SX') - m2 = ConfigMaterial.load(ref_path/'material.yaml') + m2 = ConfigMaterial.load(res_path/'material.yaml') for k in m2['phase']: m2 = m2.material_add(phase=[k],O=[1.0,0.0,0.0,0.0],homogenization='SX') assert not m2['phase'].get(k) is None @@ -109,14 +130,14 @@ class TestConfigMaterial: def test_from_table_with_constant(self): N = np.random.randint(3,10) a = np.vstack((np.hstack((np.arange(N),np.arange(N)[::-1])), - np.ones(N*2),np.zeros(N*2),np.ones(N*2),np.ones(N*2), + np.zeros(N*2),np.ones(N*2),np.zeros(N*2),np.zeros(N*2), np.ones(N*2), )).T t = Table({'varying':1,'constant':4,'ones':1},a) c = ConfigMaterial.from_table(t,**{'phase':'varying','O':'constant','homogenization':1}) assert len(c['material']) == N for i,m in enumerate(c['material']): - assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [1,0,1,1]).all() + assert m['homogenization'] == 1 and (m['constituents'][0]['O'] == [0,1,0,0]).all() @pytest.mark.parametrize('N,n,kw',[ (1,1,{'phase':'Gold', @@ -137,19 +158,32 @@ class TestConfigMaterial: assert len(m['material']) == N assert len(m['material'][0]['constituents']) == n + @pytest.mark.parametrize('shape',[(),(4,),(5,2)]) + @pytest.mark.parametrize('kw',[{'V_e':np.random.rand(3,3)}, + {'O':np.random.rand(4)}, + {'v':np.array(2)}]) + def test_material_add_invalid(self,kw,shape): + kw = {arg:np.broadcast_to(val,shape+val.shape) for arg,val in kw.items()} + with pytest.raises(ValueError): + ConfigMaterial().material_add(**kw) + + @pytest.mark.parametrize('v',[2,np.ones(3)*2,np.ones((2,2))]) + def test_material_add_invalid_v(self,v): + with pytest.raises(ValueError): + ConfigMaterial().material_add(v=v) @pytest.mark.parametrize('cell_ensemble_data',[None,'CellEnsembleData']) - def test_load_DREAM3D(self,ref_path,cell_ensemble_data): - grain_c = ConfigMaterial.load_DREAM3D(ref_path/'2phase_irregularGrid.dream3d','Grain Data', + def test_load_DREAM3D(self,res_path,cell_ensemble_data): + grain_c = ConfigMaterial.load_DREAM3D(res_path/'2phase_irregularGrid.dream3d','Grain Data', cell_ensemble_data = cell_ensemble_data) - point_c = ConfigMaterial.load_DREAM3D(ref_path/'2phase_irregularGrid.dream3d', + point_c = ConfigMaterial.load_DREAM3D(res_path/'2phase_irregularGrid.dream3d', cell_ensemble_data = cell_ensemble_data) assert point_c.is_valid and grain_c.is_valid and \ len(point_c['material'])+1 == len(grain_c['material']) - grain_m = Grid.load_DREAM3D(ref_path/'2phase_irregularGrid.dream3d','FeatureIds').material.flatten() - point_m = Grid.load_DREAM3D(ref_path/'2phase_irregularGrid.dream3d').material.flatten() + grain_m = Grid.load_DREAM3D(res_path/'2phase_irregularGrid.dream3d','FeatureIds').material.flatten() + point_m = Grid.load_DREAM3D(res_path/'2phase_irregularGrid.dream3d').material.flatten() for i in np.unique(point_m): j = int(grain_m[(point_m==i).nonzero()[0][0]]) @@ -159,11 +193,11 @@ class TestConfigMaterial: grain_c['material'][j]['constituents'][0]['phase'] - def test_load_DREAM3D_reference(self,tmp_path,ref_path,update): - cur = ConfigMaterial.load_DREAM3D(ref_path/'measured.dream3d') - ref = ConfigMaterial.load(ref_path/'measured.material.yaml') + def test_load_DREAM3D_reference(self,tmp_path,res_path,update): + cur = ConfigMaterial.load_DREAM3D(res_path/'measured.dream3d') + ref = ConfigMaterial.load(res_path/'measured.material.yaml') if update: - cur.save(ref_path/'measured.material.yaml') + cur.save(res_path/'measured.material.yaml') for i,m in enumerate(ref['material']): assert Rotation(m['constituents'][0]['O']).isclose(Rotation(cur['material'][i]['constituents'][0]['O'])) assert cur.is_valid and cur['phase'] == ref['phase'] and cur['homogenization'] == ref['homogenization'] diff --git a/python/tests/test_Grid.py b/python/tests/test_Grid.py index 43207b1e4..237ea32e5 100644 --- a/python/tests/test_Grid.py +++ b/python/tests/test_Grid.py @@ -2,7 +2,7 @@ import sys import pytest import numpy as np -import vtk +from vtkmodules.vtkCommonCore import vtkVersion from damask import VTK from damask import Grid @@ -34,9 +34,9 @@ def random(): return Grid.from_Voronoi_tessellation(cells,size,s) @pytest.fixture -def ref_path(ref_path_base): - """Directory containing reference results.""" - return ref_path_base/'Grid' +def res_path(res_path_base): + """Directory containing testing resources.""" + return res_path_base/'Grid' class TestGrid: @@ -98,20 +98,17 @@ class TestGrid: size=np.ones(3), origin=np.ones(4)) - def test_invalid_materials_shape(self,default): material = np.ones((3,3)) with pytest.raises(ValueError): Grid(material, size=np.ones(3)) - def test_invalid_materials_type(self,default): material = np.random.randint(1,300,(3,4,5))==1 with pytest.raises(TypeError): Grid(material) - @pytest.mark.parametrize('directions,reflect',[ (['x'], False), (['x','y','z'],True), @@ -119,19 +116,23 @@ class TestGrid: (['y','z'], False) ] ) - def test_mirror(self,default,update,ref_path,directions,reflect): + def test_mirror(self,default,update,res_path,directions,reflect): modified = default.mirror(directions,reflect) tag = f'directions_{"-".join(directions)}+reflect_{reflect}' - reference = ref_path/f'mirror_{tag}.vti' + reference = res_path/f'mirror_{tag}.vti' if update: modified.save(reference) assert Grid.load(reference) == modified - @pytest.mark.parametrize('directions',[(1,2,'y'),('a','b','x'),[1]]) def test_mirror_invalid(self,default,directions): with pytest.raises(ValueError): default.mirror(directions) + @pytest.mark.parametrize('reflect',[True,False]) + def test_mirror_order_invariant(self,default,reflect): + direction = np.array(['x','y','z']) + assert default.mirror(np.random.permutation(direction),reflect=reflect) \ + == default.mirror(np.random.permutation(direction),reflect=reflect) @pytest.mark.parametrize('directions',[ ['x'], @@ -140,35 +141,43 @@ class TestGrid: ['y','z'], ] ) - def test_flip(self,default,update,ref_path,directions): + def test_flip(self,default,update,res_path,directions): modified = default.flip(directions) tag = f'directions_{"-".join(directions)}' - reference = ref_path/f'flip_{tag}.vti' + reference = res_path/f'flip_{tag}.vti' if update: modified.save(reference) assert Grid.load(reference) == modified + def test_flip_order_invariant(self,default): + direction = np.array(['x','y','z']) + assert default.flip(np.random.permutation(direction)) \ + == default.flip(np.random.permutation(direction)) - def test_flip_invariant(self,default): - assert default == default.flip([]) + def test_flip_mirrored_invariant(self,default): + direction = np.random.permutation(['x','y','z']) + assert default.mirror(direction,True) == default.mirror(direction,True).flip(direction) + def test_flip_equal_halfspin(self,default): + direction = ['x','y','z'] + i = np.random.choice(3) + assert default.rotate(Rotation.from_axis_angle(np.hstack((np.identity(3)[i],180)),degrees=True)) \ + == default.flip(direction[:i]+direction[i+1:]) @pytest.mark.parametrize('direction',[['x'],['x','y']]) def test_flip_double(self,default,direction): assert default == default.flip(direction).flip(direction) - @pytest.mark.parametrize('directions',[(1,2,'y'),('a','b','x'),[1]]) def test_flip_invalid(self,default,directions): with pytest.raises(ValueError): default.flip(directions) - @pytest.mark.parametrize('distance',[1.,np.sqrt(3)]) @pytest.mark.parametrize('selection',[None,1,[1],[1,2,3]]) @pytest.mark.parametrize('periodic',[True,False]) - def test_clean_reference(self,default,update,ref_path,distance,selection,periodic): + def test_clean_reference(self,default,update,res_path,distance,selection,periodic): current = default.clean(distance,selection,periodic=periodic,rng_seed=0) - reference = ref_path/f'clean_{distance}_{util.srepr(selection,"+")}_{periodic}.vti' + reference = res_path/f'clean_{distance}_{util.srepr(selection,"+")}_{periodic}.vti' if update: current.save(reference) assert Grid.load(reference) == current @@ -184,7 +193,6 @@ class TestGrid: assert random.clean(selection=None,invert_selection=True,rng_seed=0) == random.clean(rng_seed=0) and \ random.clean(selection=None,invert_selection=False,rng_seed=0) == random.clean(rng_seed=0) - @pytest.mark.parametrize('cells',[ (10,11,10), [10,13,10], @@ -194,14 +202,13 @@ class TestGrid: np.array((10,20,2)) ] ) - def test_scale(self,default,update,ref_path,cells): + def test_scale(self,default,update,res_path,cells): modified = default.scale(cells) tag = f'grid_{util.srepr(cells,"-")}' - reference = ref_path/f'scale_{tag}.vti' + reference = res_path/f'scale_{tag}.vti' if update: modified.save(reference) assert Grid.load(reference) == modified - def test_renumber(self,default): material = default.material.copy() for m in np.unique(material): @@ -213,7 +220,6 @@ class TestGrid: assert not default == modified assert default == modified.renumber() - def test_assemble(self): cells = np.random.randint(8,16,3) N = cells.prod() @@ -221,7 +227,6 @@ class TestGrid: idx = np.random.randint(0,N,N).reshape(cells) assert (idx == g.assemble(idx).material).all - def test_substitute(self,default): offset = np.random.randint(1,500) modified = Grid(default.material + offset, @@ -257,17 +262,15 @@ class TestGrid: modified.rotate(Rotation.from_axis_angle(axis_angle,degrees=True)) assert default == modified - @pytest.mark.parametrize('Eulers',[[32.0,68.0,21.0], [0.0,32.0,240.0]]) - def test_rotate(self,default,update,ref_path,Eulers): + def test_rotate(self,default,update,res_path,Eulers): modified = default.rotate(Rotation.from_Euler_angles(Eulers,degrees=True)) tag = f'Eulers_{util.srepr(Eulers,"-")}' - reference = ref_path/f'rotate_{tag}.vti' + reference = res_path/f'rotate_{tag}.vti' if update: modified.save(reference) assert Grid.load(reference) == modified - def test_canvas_extend(self,default): cells = default.cells cells_add = np.random.randint(0,30,(3)) @@ -364,14 +367,12 @@ class TestGrid: assert random.vicinity_offset(selection=None,invert_selection=False) == random.vicinity_offset() and \ random.vicinity_offset(selection=None,invert_selection=True ) == random.vicinity_offset() - @pytest.mark.parametrize('periodic',[True,False]) def test_vicinity_offset_invariant(self,default,periodic): offset = default.vicinity_offset(selection=[default.material.max()+1, default.material.min()-1]) assert np.all(offset.material==default.material) - @pytest.mark.parametrize('periodic',[True,False]) def test_tessellation_approaches(self,periodic): cells = np.random.randint(10,20,3) @@ -382,7 +383,6 @@ class TestGrid: Laguerre = Grid.from_Laguerre_tessellation(cells,size,seeds,np.ones(N_seeds),np.arange(N_seeds)+5,periodic) assert Laguerre == Voronoi - def test_Laguerre_weights(self): cells = np.random.randint(10,20,3) size = np.random.random(3) + 1.0 @@ -394,7 +394,6 @@ class TestGrid: Laguerre = Grid.from_Laguerre_tessellation(cells,size,seeds,weights,periodic=np.random.random()>0.5) assert np.all(Laguerre.material == ms) - @pytest.mark.parametrize('approach',['Laguerre','Voronoi']) def test_tessellate_bicrystal(self,approach): cells = np.random.randint(5,10,3)*2 @@ -408,7 +407,6 @@ class TestGrid: grid = Grid.from_Voronoi_tessellation(cells,size,seeds, periodic=np.random.random()>0.5) assert np.all(grid.material == material) - @pytest.mark.parametrize('surface',['Schwarz P', 'Double Primitive', 'Schwarz D', @@ -450,7 +448,6 @@ class TestGrid: grid = Grid.from_minimal_surface(cells,np.ones(3),surface,threshold) assert np.isclose(np.count_nonzero(grid.material==1)/np.prod(grid.cells),.5,rtol=1e-3) - def test_from_table(self): cells = np.random.randint(60,100,3) size = np.ones(3)+np.random.rand(3) @@ -462,7 +459,6 @@ class TestGrid: g = Grid.from_table(t,'coords',['indicator','z']) assert g.N_materials == g.cells[0]*2 and (g.material[:,:,-1]-g.material[:,:,0] == cells[0]).all() - def test_from_table_recover(self,tmp_path): cells = np.random.randint(60,100,3) size = np.ones(3)+np.random.rand(3) @@ -472,16 +468,15 @@ class TestGrid: t = Table({'c':3,'m':1},np.column_stack((coords.reshape(-1,3,order='F'),grid.material.flatten(order='F')))) assert grid.sort().renumber() == Grid.from_table(t,'c',['m']) - @pytest.mark.parametrize('periodic',[True,False]) @pytest.mark.parametrize('direction',['x','y','z',['x','y'],'zy','xz',['x','y','z']]) - @pytest.mark.xfail(int(vtk.vtkVersion.GetVTKVersion().split('.')[0])<8, reason='missing METADATA') - def test_get_grain_boundaries(self,update,ref_path,periodic,direction): - grid = Grid.load(ref_path/'get_grain_boundaries_8g12x15x20.vti') + @pytest.mark.xfail(vtkVersion.GetVTKMajorVersion()<8, reason='missing METADATA') + def test_get_grain_boundaries(self,update,res_path,periodic,direction): + grid = Grid.load(res_path/'get_grain_boundaries_8g12x15x20.vti') current = grid.get_grain_boundaries(periodic,direction) if update: - current.save(ref_path/f'get_grain_boundaries_8g12x15x20_{direction}_{periodic}.vtu',parallel=False) - reference = VTK.load(ref_path/f'get_grain_boundaries_8g12x15x20_{"".join(direction)}_{periodic}.vtu') + current.save(res_path/f'get_grain_boundaries_8g12x15x20_{direction}_{periodic}.vtu',parallel=False) + reference = VTK.load(res_path/f'get_grain_boundaries_8g12x15x20_{"".join(direction)}_{periodic}.vtu') assert current.__repr__() == reference.__repr__() @pytest.mark.parametrize('directions',[(1,2,'y'),('a','b','x'),[1]]) @@ -489,27 +484,26 @@ class TestGrid: with pytest.raises(ValueError): default.get_grain_boundaries(directions=directions) - def test_load_DREAM3D(self,ref_path): - grain = Grid.load_DREAM3D(ref_path/'2phase_irregularGrid.dream3d','FeatureIds') - point = Grid.load_DREAM3D(ref_path/'2phase_irregularGrid.dream3d') + def test_load_DREAM3D(self,res_path): + grain = Grid.load_DREAM3D(res_path/'2phase_irregularGrid.dream3d','FeatureIds') + point = Grid.load_DREAM3D(res_path/'2phase_irregularGrid.dream3d') assert np.allclose(grain.origin,point.origin) and \ np.allclose(grain.size,point.size) and \ (grain.sort().material == point.material+1).all() - - def test_load_DREAM3D_reference(self,ref_path,update): - current = Grid.load_DREAM3D(ref_path/'measured.dream3d') - reference = Grid.load(ref_path/'measured.vti') + def test_load_DREAM3D_reference(self,res_path,update): + current = Grid.load_DREAM3D(res_path/'measured.dream3d') + reference = Grid.load(res_path/'measured.vti') if update: - current.save(ref_path/'measured.vti') + current.save(res_path/'measured.vti') assert current == reference - def test_load_Neper_reference(self,ref_path,update): - current = Grid.load_Neper(ref_path/'n10-id1_scaled.vtk') - reference = Grid.load(ref_path/'n10-id1_scaled.vti') + def test_load_Neper_reference(self,res_path,update): + current = Grid.load_Neper(res_path/'n10-id1_scaled.vtk').renumber() + reference = Grid.load(res_path/'n10-id1_scaled.vti') if update: - current.save(ref_path/'n10-id1_scaled.vti') + current.save(res_path/'n10-id1_scaled.vti') assert current == reference diff --git a/python/tests/test_LoadcaseGrid.py b/python/tests/test_LoadcaseGrid.py new file mode 100644 index 000000000..54649d0c5 --- /dev/null +++ b/python/tests/test_LoadcaseGrid.py @@ -0,0 +1,22 @@ +import numpy as np +from numpy import ma + +from damask import LoadcaseGrid + +class TestGridConfig: + + def test_dumper(self): + a = ma.MaskedArray(np.arange(3,dtype=float),mask=[0,1,0]) + assert str(LoadcaseGrid({'a':a})) == 'a: [0.0, x, 2.0]\n' + assert str(LoadcaseGrid({'a':a.astype(int)})) == 'a: [0, x, 2]\n' + assert str(LoadcaseGrid({'a':a.data})) == 'a: [0.0, 1.0, 2.0]\n' + + def test_init(self): + assert LoadcaseGrid() \ + == LoadcaseGrid({'solver':{}, + 'loadstep':[], + }) + assert LoadcaseGrid(solver={'mechanical':'spectral_basic'}) \ + == LoadcaseGrid({'solver':{'mechanical':'spectral_basic'}, + 'loadstep':[], + }) diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 67fbeb51d..a45444908 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -13,9 +13,9 @@ crystal_families = set(_crystal.lattice_symmetries.values()) @pytest.fixture -def ref_path(ref_path_base): - """Directory containing reference results.""" - return ref_path_base/'Orientation' +def res_path(res_path_base): + """Directory containing testing resources.""" + return res_path_base/'Orientation' @pytest.fixture def set_of_rodrigues(set_of_quaternions): @@ -313,8 +313,8 @@ class TestOrientation: @pytest.mark.parametrize('model',['Bain','KS','GT','GT_prime','NW','Pitsch']) @pytest.mark.parametrize('lattice',['cF','cI']) - def test_relationship_reference(self,update,ref_path,model,lattice): - reference = ref_path/f'{lattice}_{model}.txt' + def test_relationship_reference(self,update,res_path,model,lattice): + reference = res_path/f'{lattice}_{model}.txt' o = Orientation(lattice=lattice) eu = o.related(model).as_Euler_angles(degrees=True) if update: @@ -363,10 +363,10 @@ class TestOrientation: == o.shape + vector.shape[:-1] + (o.symmetry_operations.shape if with_symmetry else ()) + vector.shape[-1:] @pytest.mark.parametrize('lattice',['hP','cI','cF']) #tI not included yet - def test_Schmid(self,update,ref_path,lattice): + def test_Schmid(self,update,res_path,lattice): O = Orientation(lattice=lattice) # noqa for mode in ['slip','twin']: - reference = ref_path/f'{lattice}_{mode}.txt' + reference = res_path/f'{lattice}_{mode}.txt' P = O.Schmid(N_slip='*') if mode == 'slip' else O.Schmid(N_twin='*') if update: table = Table(P.reshape(-1,9),{'Schmid':(3,3,)}) diff --git a/python/tests/test_Result.py b/python/tests/test_Result.py index f0de16937..a775e1c2d 100644 --- a/python/tests/test_Result.py +++ b/python/tests/test_Result.py @@ -10,7 +10,12 @@ import random from datetime import datetime import pytest -import vtk +from vtkmodules.vtkIOXML import vtkXMLImageDataReader +from vtkmodules.vtkCommonCore import vtkVersion +try: + from vtkmodules.vtkIOXdmf2 import vtkXdmfReader +except ImportError: + vtkXdmfReader=None # noqa type: ignore import h5py import numpy as np @@ -23,23 +28,23 @@ from damask import grid_filters @pytest.fixture -def default(tmp_path,ref_path): +def default(tmp_path,res_path): """Small Result file in temp location for modification.""" fname = '12grains6x7x8_tensionY.hdf5' - shutil.copy(ref_path/fname,tmp_path) + shutil.copy(res_path/fname,tmp_path) return Result(tmp_path/fname).view(times=20.0) @pytest.fixture -def single_phase(tmp_path,ref_path): +def single_phase(tmp_path,res_path): """Single phase Result file in temp location for modification.""" fname = '6grains6x7x8_single_phase_tensionY.hdf5' - shutil.copy(ref_path/fname,tmp_path) + shutil.copy(res_path/fname,tmp_path) return Result(tmp_path/fname) @pytest.fixture -def ref_path(ref_path_base): - """Directory containing reference results.""" - return ref_path_base/'Result' +def res_path(res_path_base): + """Directory containing testing resources.""" + return res_path_base/'Result' def dict_equal(d1, d2): for k in d1: @@ -290,8 +295,8 @@ class TestResult: with pytest.raises(TypeError): default.add_calculation('#invalid#*2') - def test_add_generic_grid_invalid(self,ref_path): - result = Result(ref_path/'4grains2x4x3_compressionY.hdf5') + def test_add_generic_grid_invalid(self,res_path): + result = Result(res_path/'4grains2x4x3_compressionY.hdf5') with pytest.raises(NotImplementedError): result.add_curl('F') @@ -385,33 +390,35 @@ class TestResult: assert np.allclose(a,b) @pytest.mark.parametrize('output',['F','*',['P'],['P','F']],ids=range(4)) - @pytest.mark.parametrize('fname',['12grains6x7x8_tensionY.hdf5'],ids=range(1)) + @pytest.mark.parametrize('fname',['12grains6x7x8_tensionY.hdf5', + '4grains2x4x3_compressionY.hdf5', + '6grains6x7x8_single_phase_tensionY.hdf5'],ids=range(3)) @pytest.mark.parametrize('inc',[4,0],ids=range(2)) - @pytest.mark.xfail(int(vtk.vtkVersion.GetVTKVersion().split('.')[0])<9, reason='missing "Direction" attribute') - def test_export_vtk(self,request,tmp_path,ref_path,update,patch_execution_stamp,patch_datetime_now,output,fname,inc): - result = Result(ref_path/fname).view(increments=inc) + @pytest.mark.xfail(vtkVersion.GetVTKMajorVersion()<9, reason='missing "Direction" attribute') + def test_export_vtk(self,request,tmp_path,res_path,update,patch_execution_stamp,patch_datetime_now,output,fname,inc): + result = Result(res_path/fname).view(increments=inc) result.export_VTK(output,target_dir=tmp_path,parallel=False) fname = fname.split('.')[0]+f'_inc{(inc if type(inc) == int else inc[0]):0>2}.vti' v = VTK.load(tmp_path/fname) v.comments = ['n/a'] v.save(tmp_path/fname,parallel=False) - with open(tmp_path/fname) as f: - cur = hashlib.md5(f.read().encode()).hexdigest() + with open(tmp_path/fname,'rb') as f: + cur = hashlib.md5(f.read()).hexdigest() if update: - with open((ref_path/'export_VTK'/request.node.name).with_suffix('.md5'),'w') as f: + with open((res_path/'export_VTK'/request.node.name).with_suffix('.md5'),'w') as f: f.write(cur+'\n') - with open((ref_path/'export_VTK'/request.node.name).with_suffix('.md5')) as f: + with open((res_path/'export_VTK'/request.node.name).with_suffix('.md5')) as f: assert cur == f.read().strip('\n') @pytest.mark.parametrize('mode',['point','cell']) @pytest.mark.parametrize('output',[False,True]) - def test_export_vtk_marc(self,tmp_path,ref_path,mode,output): + def test_export_vtk_marc(self,tmp_path,res_path,mode,output): os.chdir(tmp_path) - result = Result(ref_path/'check_compile_job1.hdf5') + result = Result(res_path/'check_compile_job1.hdf5') result.export_VTK(output,mode) - def test_marc_coordinates(self,ref_path): - result = Result(ref_path/'check_compile_job1.hdf5').view(increments=-1) + def test_marc_coordinates(self,res_path): + result = Result(res_path/'check_compile_job1.hdf5').view(increments=-1) c_n = result.coordinates0_node + result.get('u_n') c_p = result.coordinates0_point + result.get('u_p') assert len(c_n) > len(c_p) @@ -430,22 +437,21 @@ class TestResult: single_phase.export_VTK(mode='point',target_dir=export_dir,parallel=False) assert set(os.listdir(export_dir)) == set([f'{single_phase.fname.stem}_inc{i:02}.vtp' for i in range(0,40+1,4)]) - def test_XDMF_datatypes(self,tmp_path,single_phase,update,ref_path): + def test_XDMF_datatypes(self,tmp_path,single_phase,update,res_path): for what,shape in {'scalar':(),'vector':(3,),'tensor':(3,3),'matrix':(12,)}.items(): for dtype in ['f4','f8','i1','i2','i4','i8','u1','u2','u4','u8']: single_phase.add_calculation(f"np.ones(np.shape(#F#)[0:1]+{shape},'{dtype}')",f'{what}_{dtype}') xdmf_path = tmp_path/single_phase.fname.with_suffix('.xdmf').name single_phase.export_XDMF(target_dir=tmp_path) if update: - shutil.copy(xdmf_path,ref_path/xdmf_path.name) - assert sorted(open(xdmf_path).read()) == sorted(open(ref_path/xdmf_path.name).read()) + shutil.copy(xdmf_path,res_path/xdmf_path.name) + assert sorted(open(xdmf_path).read()) == sorted(open(res_path/xdmf_path.name).read()) - @pytest.mark.skipif(not (hasattr(vtk,'vtkXdmfReader') and hasattr(vtk.vtkXdmfReader(),'GetOutput')), - reason='https://discourse.vtk.org/t/2450') + @pytest.mark.skipif(not hasattr(vtkXdmfReader,'GetOutput'),reason='https://discourse.vtk.org/t/2450') def test_XDMF_shape(self,tmp_path,single_phase): single_phase.export_XDMF(target_dir=single_phase.fname.parent) fname = single_phase.fname.with_suffix('.xdmf') - reader_xdmf = vtk.vtkXdmfReader() + reader_xdmf = vtkXdmfReader() reader_xdmf.SetFileName(fname) reader_xdmf.Update() dim_xdmf = reader_xdmf.GetOutput().GetDimensions() @@ -453,7 +459,7 @@ class TestResult: single_phase.view(increments=0).export_VTK(target_dir=single_phase.fname.parent,parallel=False) fname = single_phase.fname.with_name(single_phase.fname.stem+'_inc00.vti') - reader_vti = vtk.vtkXMLImageDataReader() + reader_vti = vtkXMLImageDataReader() reader_vti.SetFileName(fname) reader_vti.Update() dim_vti = reader_vti.GetOutput().GetDimensions() @@ -472,11 +478,10 @@ class TestResult: single_phase.export_XDMF(target_dir=export_dir) assert single_phase.fname.with_suffix('.xdmf').name in os.listdir(export_dir) - @pytest.mark.skipif(not (hasattr(vtk,'vtkXdmfReader') and hasattr(vtk.vtkXdmfReader(),'GetOutput')), - reason='https://discourse.vtk.org/t/2450') + @pytest.mark.skipif(not hasattr(vtkXdmfReader,'GetOutput'),reason='https://discourse.vtk.org/t/2450') def test_XDMF_relabs_path(self,single_phase,tmp_path): def dims(xdmf): - reader_xdmf = vtk.vtkXdmfReader() + reader_xdmf = vtkXdmfReader() reader_xdmf.SetFileName(xdmf) reader_xdmf.Update() return reader_xdmf.GetOutput().GetDimensions() @@ -508,18 +513,18 @@ class TestResult: ({'phases':False},['Delta_V'],True,True), ({},['u_p','u_n'],False,False)], ids=list(range(8))) - def test_get(self,update,request,ref_path,view,output,flatten,prune): - result = Result(ref_path/'4grains2x4x3_compressionY.hdf5') + def test_get(self,update,request,res_path,view,output,flatten,prune): + result = Result(res_path/'4grains2x4x3_compressionY.hdf5') for key,value in view.items(): result = result.view(**{key:value}) fname = request.node.name cur = result.get(output,flatten,prune) if update: - with bz2.BZ2File((ref_path/'get'/fname).with_suffix('.pbz2'),'w') as f: + with bz2.BZ2File((res_path/'get'/fname).with_suffix('.pbz2'),'w') as f: pickle.dump(cur,f) - with bz2.BZ2File((ref_path/'get'/fname).with_suffix('.pbz2')) as f: + with bz2.BZ2File((res_path/'get'/fname).with_suffix('.pbz2')) as f: ref = pickle.load(f) assert cur is None if ref is None else dict_equal(cur,ref) @@ -533,18 +538,18 @@ class TestResult: ({'phases':False},['Delta_V'],True,True,[1,2,4]), ({},['u_p','u_n'],False,False,None)], ids=list(range(8))) - def test_place(self,update,request,ref_path,view,output,flatten,prune,constituents): - result = Result(ref_path/'4grains2x4x3_compressionY.hdf5') + def test_place(self,update,request,res_path,view,output,flatten,prune,constituents): + result = Result(res_path/'4grains2x4x3_compressionY.hdf5') for key,value in view.items(): result = result.view(**{key:value}) fname = request.node.name cur = result.place(output,flatten,prune,constituents) if update: - with bz2.BZ2File((ref_path/'place'/fname).with_suffix('.pbz2'),'w') as f: + with bz2.BZ2File((res_path/'place'/fname).with_suffix('.pbz2'),'w') as f: pickle.dump(cur,f) - with bz2.BZ2File((ref_path/'place'/fname).with_suffix('.pbz2')) as f: + with bz2.BZ2File((res_path/'place'/fname).with_suffix('.pbz2')) as f: ref = pickle.load(f) assert cur is None if ref is None else dict_equal(cur,ref) @@ -571,38 +576,40 @@ class TestResult: @pytest.mark.parametrize('output',['12grains6x7x8.vti', 'tensionY.yaml', ]) - def test_export_simulation_setup_content(self,ref_path,tmp_path,default,output): + def test_export_simulation_setup_content(self,res_path,tmp_path,default,output): default.export_simulation_setup(output,target_dir=tmp_path,overwrite=True) - assert open(tmp_path/output).read() == open(ref_path/output).read() + assert open(tmp_path/output).read() == open(res_path/output).read() @pytest.mark.parametrize('fname',['4grains2x4x3_compressionY.hdf5', '6grains6x7x8_single_phase_tensionY.hdf5']) @pytest.mark.parametrize('output',['material.yaml','*']) - def test_export_simulation_setup_consistency(self,ref_path,tmp_path,fname,output): - r = Result(ref_path/fname) + def test_export_simulation_setup_consistency(self,res_path,tmp_path,fname,output): + r = Result(res_path/fname) r.export_simulation_setup(output,target_dir=tmp_path) - with h5py.File(ref_path/fname,'r') as f_hdf5: + with h5py.File(res_path/fname,'r') as f_hdf5: for file in fnmatch.filter(f_hdf5['setup'].keys(),output): with open(tmp_path/file) as f: assert f_hdf5[f'setup/{file}'][()][0].decode() == f.read() - def test_export_simulation_setup_custom_path(self,ref_path,tmp_path): + def test_export_simulation_setup_custom_path(self,res_path,tmp_path): subdir = 'export_dir' absdir = tmp_path/subdir absdir.mkdir(exist_ok=True) - r = Result(ref_path/'4grains2x4x3_compressionY.hdf5') + r = Result(res_path/'4grains2x4x3_compressionY.hdf5') for t,cwd in zip([absdir,subdir,None],[tmp_path,tmp_path,absdir]): os.chdir(cwd) r.export_simulation_setup('material.yaml',target_dir=t) assert 'material.yaml' in os.listdir(absdir); (absdir/'material.yaml').unlink() @pytest.mark.parametrize('fname',['4grains2x4x3_compressionY.hdf5', - '6grains6x7x8_single_phase_tensionY.hdf5']) - def test_export_DADF5(self,ref_path,tmp_path,fname): - r = Result(ref_path/fname) + '6grains6x7x8_single_phase_tensionY.hdf5', + '12grains6x7x8_tensionY.hdf5', + 'check_compile_job1.hdf5',]) + def test_export_DADF5(self,res_path,tmp_path,fname): + r = Result(res_path/fname) r = r.view(phases = random.sample(r.phases,1)) - r = r.view(increments = random.sample(r.increments,np.random.randint(2,len(r.increments)))) + r = r.view(increments = random.sample(r.increments,np.random.randint(1,len(r.increments)))) r.export_DADF5(tmp_path/fname) r_exp = Result(tmp_path/fname) assert str(r.get()) == str(r_exp.get()) @@ -610,7 +617,16 @@ class TestResult: @pytest.mark.parametrize('fname',['4grains2x4x3_compressionY.hdf5', '6grains6x7x8_single_phase_tensionY.hdf5']) - def test_export_DADF5_name_clash(self,ref_path,tmp_path,fname): - r = Result(ref_path/fname) + def test_export_DADF5_name_clash(self,res_path,tmp_path,fname): + r = Result(res_path/fname) with pytest.raises(PermissionError): r.export_DADF5(r.fname) + + @pytest.mark.parametrize('fname',['4grains2x4x3_compressionY.hdf5', + '6grains6x7x8_single_phase_tensionY.hdf5', + '12grains6x7x8_tensionY.hdf5']) + def test_export_DADF5_regrid(self,res_path,tmp_path,fname): + r = Result(res_path/fname) + m = grid_filters.regrid(r.size,np.broadcast_to(np.eye(3),tuple(r.cells)+(3,3)),r.cells*2) + r.export_DADF5(tmp_path/'regridded.hdf5',mapping=m) + assert np.all(Result(tmp_path/'regridded.hdf5').cells == r.cells*2) diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index 3cce0fcf1..6e135212f 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -12,9 +12,9 @@ n = 1000 atol=1.e-4 @pytest.fixture -def ref_path(ref_path_base): - """Directory containing reference results.""" - return ref_path_base/'Rotation' +def res_path(res_path_base): + """Directory containing testing resources.""" + return res_path_base/'Rotation' @pytest.fixture def set_of_rotations(set_of_quaternions): @@ -774,9 +774,11 @@ class TestRotation: ).all() - def test_matrix(self,multidim_rotations): + @pytest.mark.parametrize('normalize',[True,False]) + def test_matrix(self,multidim_rotations,normalize): m = multidim_rotations - o = Rotation.from_matrix(m.as_matrix()) + o = Rotation.from_matrix(m.as_matrix()*(0.9 if normalize else 1.0), + normalize=normalize) f = Rotation(np.where(np.isclose(m.as_quaternion()[...,0],0.0,atol=atol)[...,np.newaxis],~o,o)) assert np.logical_or(m.isclose(o,atol=atol), m.isclose(f,atol=atol) @@ -1177,12 +1179,12 @@ class TestRotation: @pytest.mark.parametrize('fractions',[True,False]) @pytest.mark.parametrize('degrees',[True,False]) @pytest.mark.parametrize('shape',[2**13,2**14,2**15,(2**8,2**6)]) - def test_ODF_cell(self,ref_path,fractions,degrees,shape): + def test_ODF_cell(self,res_path,fractions,degrees,shape): steps = np.array([144,36,36]) limits = np.array([360.,90.,90.]) rng = tuple(zip(np.zeros(3),limits)) - weights = Table.load(ref_path/'ODF_experimental_cell.txt').get('intensity').flatten() + weights = Table.load(res_path/'ODF_experimental_cell.txt').get('intensity').flatten() Eulers = grid_filters.coordinates0_point(steps,limits) Eulers = np.radians(Eulers) if not degrees else Eulers @@ -1193,12 +1195,12 @@ class TestRotation: @pytest.mark.parametrize('degrees',[True,False]) @pytest.mark.parametrize('shape',[2**13,2**14,2**15,(2**8,2**6)]) - def test_ODF_node(self,ref_path,degrees,shape): + def test_ODF_node(self,res_path,degrees,shape): steps = np.array([144,36,36]) limits = np.array([360.,90.,90.]) rng = tuple(zip(-limits/steps*.5,limits-limits/steps*.5)) - weights = Table.load(ref_path/'ODF_experimental.txt').get('intensity') + weights = Table.load(res_path/'ODF_experimental.txt').get('intensity') weights = weights.reshape(steps+1,order='F')[:-1,:-1,:-1].reshape(-1,order='F') Eulers = grid_filters.coordinates0_node(steps,limits)[:-1,:-1,:-1] diff --git a/python/tests/test_Table.py b/python/tests/test_Table.py index 5eb950817..6d922b7cc 100644 --- a/python/tests/test_Table.py +++ b/python/tests/test_Table.py @@ -13,9 +13,9 @@ def default(): ['test data','contains five rows of only ones']) @pytest.fixture -def ref_path(ref_path_base): - """Directory containing reference results.""" - return ref_path_base/'Table' +def res_path(res_path_base): + """Directory containing testing resources.""" + return res_path_base/'Table' class TestTable: @@ -81,13 +81,15 @@ class TestTable: assert default[N:].get('F').shape == (len(default)-N,3,3) assert default[:N,['v','s']].data.equals(default['v','s'][:N].data) - @pytest.mark.parametrize('mode',['str','path']) - def test_write_read(self,default,tmp_path,mode): - default.save(tmp_path/'default.txt') - if mode == 'path': - new = Table.load(tmp_path/'default.txt') - elif mode == 'str': - new = Table.load(str(tmp_path/'default.txt')) + @pytest.mark.parametrize('mode',['str','path','file']) + def test_write_read_mode(self,default,tmp_path,mode): + path = tmp_path/'default.txt' + if mode == 'file': + default.save(open(path,'w')) + new = Table.load(open(path)) + else: + default.save(str(path) if mode == 'str' else path) + new = Table.load(str(path) if mode == 'str' else path) assert all(default.data == new.data) and default.shapes == new.shapes def test_write_read_file(self,default,tmp_path): @@ -101,30 +103,29 @@ class TestTable: with pytest.raises(TypeError): default.save(tmp_path/'shouldnotbethere.txt',format='invalid') - @pytest.mark.parametrize('mode',['str','path']) - def test_read_ang(self,ref_path,mode): - if mode == 'path': - new = Table.load_ang(ref_path/'simple.ang') - elif mode == 'str': - new = Table.load_ang(str(ref_path/'simple.ang')) + @pytest.mark.parametrize('mode',['str','path','file']) + def test_read_ang_mode(self,res_path,mode): + where = res_path/'simple.ang' + fname = {'path': where, + 'str': str(where), + 'file': open(where)}[mode] + new = Table.load_ang(fname) assert new.data.shape == (4,10) and \ new.labels == ['eu', 'pos', 'IQ', 'CI', 'ID', 'intensity', 'fit'] - def test_read_ang_file(self,ref_path): - f = open(ref_path/'simple.ang') - new = Table.load_ang(f) - assert new.data.shape == (4,10) and \ - new.labels == ['eu', 'pos', 'IQ', 'CI', 'ID', 'intensity', 'fit'] + def test_read_ang_shapes(self,res_path): + new = Table.load_ang(str(res_path/'simple.ang'),shapes={}) + assert new.data.shape == (4,10) and new.labels == ['unknown'] - def test_save_ang(self,ref_path,tmp_path): - orig = Table.load_ang(ref_path/'simple.ang') + def test_save_ang(self,res_path,tmp_path): + orig = Table.load_ang(res_path/'simple.ang') orig.save(tmp_path/'simple.ang',with_labels=False) saved = Table.load_ang(tmp_path/'simple.ang') assert saved == orig @pytest.mark.parametrize('fname',['datatype-mix.txt','whitespace-mix.txt']) - def test_read_strange(self,ref_path,fname): - with open(ref_path/fname) as f: + def test_read_strange(self,res_path,fname): + with open(res_path/fname) as f: Table.load(f) def test_rename_equivalent(self): diff --git a/python/tests/test_VTK.py b/python/tests/test_VTK.py index 2efa148b2..0368d1d16 100644 --- a/python/tests/test_VTK.py +++ b/python/tests/test_VTK.py @@ -7,16 +7,16 @@ import sys import pytest import numpy as np import numpy.ma as ma -import vtk +from vtkmodules.vtkCommonCore import vtkVersion from damask import VTK from damask import Table from damask import Colormap @pytest.fixture -def ref_path(ref_path_base): - """Directory containing reference results.""" - return ref_path_base/'VTK' +def res_path(res_path_base): + """Directory containing testing resources.""" + return res_path_base/'VTK' @pytest.fixture def default(): @@ -32,7 +32,7 @@ class TestVTK: print('patched damask.util.execution_stamp') @pytest.mark.parametrize('cmap',[Colormap.from_predefined('cividis'),'strain']) - @pytest.mark.skipif(sys.platform == 'win32', reason='DISPLAY has no effect on windows') + @pytest.mark.skipif(sys.platform == 'win32', reason='DISPLAY has no effect on Windows OS') def test_show(sef,default,cmap,monkeypatch): monkeypatch.delenv('DISPLAY',raising=False) default.show(colormap=cmap) @@ -222,19 +222,19 @@ class TestVTK: new = VTK.load(tmp_path/'with_comments.vti') assert new.comments == ['this is a comment'] - @pytest.mark.xfail(int(vtk.vtkVersion.GetVTKVersion().split('.')[0])<8, reason='missing METADATA') - def test_compare_reference_polyData(self,update,ref_path,tmp_path): + @pytest.mark.xfail(vtkVersion.GetVTKMajorVersion()<8, reason='missing METADATA') + def test_compare_reference_polyData(self,update,res_path,tmp_path): points=np.dstack((np.linspace(0.,1.,10),np.linspace(0.,2.,10),np.linspace(-1.,1.,10))).squeeze() polyData = VTK.from_poly_data(points).set('coordinates',points) if update: - polyData.save(ref_path/'polyData') + polyData.save(res_path/'polyData') else: - reference = VTK.load(ref_path/'polyData.vtp') + reference = VTK.load(res_path/'polyData.vtp') assert polyData.as_ASCII() == reference.as_ASCII() and \ np.allclose(polyData.get('coordinates'),points) - @pytest.mark.xfail(int(vtk.vtkVersion.GetVTKVersion().split('.')[0])<8, reason='missing METADATA') - def test_compare_reference_rectilinearGrid(self,update,ref_path,tmp_path): + @pytest.mark.xfail(vtkVersion.GetVTKMajorVersion()<8, reason='missing METADATA') + def test_compare_reference_rectilinearGrid(self,update,res_path,tmp_path): grid = [np.arange(4)**2., np.arange(5)**2., np.arange(6)**2.] # ParaView renders tetrahedral meshing unless using float coordinates! @@ -245,8 +245,8 @@ class TestVTK: .set('cell',np.ascontiguousarray(c)) \ .set('node',np.ascontiguousarray(n)) if update: - rectilinearGrid.save(ref_path/'rectilinearGrid') + rectilinearGrid.save(res_path/'rectilinearGrid') else: - reference = VTK.load(ref_path/'rectilinearGrid.vtr') + reference = VTK.load(res_path/'rectilinearGrid.vtr') assert rectilinearGrid.as_ASCII() == reference.as_ASCII() and \ np.allclose(rectilinearGrid.get('cell'),c) diff --git a/python/tests/test_mechanics.py b/python/tests/test_mechanics.py index 667747f8e..8557587fe 100644 --- a/python/tests/test_mechanics.py +++ b/python/tests/test_mechanics.py @@ -215,3 +215,7 @@ class TestMechanics: def test_invalid_decomposition(self): with pytest.raises(ValueError): mechanics._polar_decomposition(np.random.rand(10,3,3),'A') + + def test_invalid_strain(self): + with pytest.raises(ValueError): + mechanics.strain(np.random.rand(10,3,3),'A',0) diff --git a/python/tests/test_util.py b/python/tests/test_util.py index a7b94794b..b9964c1c1 100644 --- a/python/tests/test_util.py +++ b/python/tests/test_util.py @@ -1,5 +1,6 @@ import sys import random +import pydoc import pytest import numpy as np @@ -229,52 +230,30 @@ class TestUtil: def test_Bravais_Miller_Bravais(self,vector,kw_Miller,kw_Bravais): assert np.all(vector == util.Miller_to_Bravais(**{kw_Miller:util.Bravais_to_Miller(**{kw_Bravais:vector})})) - - @pytest.mark.parametrize('extra_parameters',[""" + @pytest.mark.parametrize('adopted_parameters',[ + pytest.param(""" p2 : str, optional p2 description 1 p2 description 2 """, - """ + id = 'standard'), + pytest.param(""" p2 : str, optional p2 description 1 p2 description 2 """, - """ + id = 'indented'), + pytest.param(""" p2 : str, optional p2 description 1 p2 description 2 - """]) - @pytest.mark.parametrize('invalid_docstring',[""" - Function description - - Parameters ---------- - p0 : numpy.ndarray, shape (...,4) - p0 description 1 - p0 description 2 - p1 : int, optional - p1 description - - Remaining description - """, - """ - Function description - - Parameters - ---------- - p0 : numpy.ndarray, shape (...,4) - p0 description 1 - p0 description 2 - p1 : int, optional - p1 description - - Remaining description - """,]) - def test_extend_docstring_parameters(self,extra_parameters,invalid_docstring): + """, + id = 'no_indent')]) + def test_extend_docstring_parameters_string(self,adopted_parameters): test_docstring = """ - Function description + Function description. Parameters ---------- @@ -284,22 +263,10 @@ p2 : str, optional p1 : int, optional p1 description - Remaining description + Remaining description\n""" + assert util._docstringer(test_docstring,adopted_parameters) ==\ """ - invalid_docstring = """ - Function description - - Parameters ---------- - p0 : numpy.ndarray, shape (...,4) - p0 description 1 - p0 description 2 - p1 : int, optional - p1 description - - Remaining description - """ - expected = """ - Function description + Function description. Parameters ---------- @@ -312,44 +279,254 @@ p2 : str, optional p2 description 1 p2 description 2 - Remaining description - """.split("\n") - assert expected == util._docstringer(test_docstring,extra_parameters).split('\n') - with pytest.raises(RuntimeError): - util._docstringer(invalid_docstring,extra_parameters) + Remaining description\n""" - def test_replace_docstring_return_type(self): + def test_extend_docstring_parameters_function(self): + test_docstring = """ + Function description. + + Parameters + ---------- + p0 : numpy.ndarray, shape (...,4) + p0 description 1 + + """ + + def testfunction_1(): + """ + Function description. + + Parameters + ---------- + p1 : int, optional + p1 description + + Notes + ----- + Function Notes 1 + Function Notes 2 + + References + ---------- + Reference 1 + + Reference 2 + + + """ + pass + + assert (test_docstring:=util._docstringer(test_docstring,adopted_references = testfunction_1)) == \ + """ + Function description. + + Parameters + ---------- + p0 : numpy.ndarray, shape (...,4) + p0 description 1 + + References + ---------- + Reference 1 + + Reference 2 + \n""" + assert (test_docstring:=util._docstringer(test_docstring,adopted_notes = testfunction_1)) == \ + """ + Function description. + + Parameters + ---------- + p0 : numpy.ndarray, shape (...,4) + p0 description 1 + + Notes + ----- + Function Notes 1 + Function Notes 2 + + References + ---------- + Reference 1 + + Reference 2 + \n""" + + def testfunction_2(): + """ + Function description. + + References + ---------- + Reference 3 + + + """ + + assert (test_docstring:=util._docstringer(test_docstring,adopted_references = testfunction_2)) == \ + """ + Function description. + + Parameters + ---------- + p0 : numpy.ndarray, shape (...,4) + p0 description 1 + + Notes + ----- + Function Notes 1 + Function Notes 2 + + References + ---------- + Reference 1 + + Reference 2 + + Reference 3 + \n""" + + def return_bound_method(): + class TestClassDecorated: + def decorated_func_bound(self) -> 'TestClassDecorated': + pass + return TestClassDecorated.decorated_func_bound + + def return_simple_function(): + class TestClassDecorated: + pass + + def decorated_func() -> TestClassDecorated: + pass + return decorated_func + + @pytest.mark.parametrize('adopted_return',[ + pytest.param(return_simple_function(), + id = 'decorated_func'), + pytest.param(return_bound_method(), + id = 'decorated_func_bound'), + pytest.param('test_util.TestClassDecorated', + id = 'decorated_func_bound')]) + def test_replace_docstring_return(self,adopted_return): class TestClassOriginal: pass def original_func() -> TestClassOriginal: pass - class TestClassDecorated: - def decorated_func_bound(self) -> 'TestClassDecorated': - pass - - def decorated_func() -> TestClassDecorated: - pass - original_func.__doc__ = """ - Function description/Parameters + Function description. Returns ------- Return value : test_util.TestClassOriginal Remaining description - """ + """ - expected = """ - Function description/Parameters + + assert util._docstringer(original_func,adopted_return=adopted_return) == """ + Function description. Returns ------- Return value : test_util.TestClassDecorated - Remaining description - """ - assert expected == util._docstringer(original_func,return_type=decorated_func) - assert expected == util._docstringer(original_func,return_type=TestClassDecorated.decorated_func_bound) + Remaining description\n""" + + + @pytest.mark.parametrize('adopted_func_doc',[ + pytest.param(""" + Function description. + + Parameters + ---------- + b : float 4 + b description + c : float 5 + c description differing + d : float 6 + d description + + Remaining description\n + """, + id = 'append'), + pytest.param(""" + Function description. + + Parameters + ---------- + d : float 6 + d description + a : float 7 + a description\n""", + id = 'insert')]) + def test_extend_docstring_overlapping_section_content(self,adopted_func_doc): + + original_func_doc = """ + Function description. + + Parameters + ---------- + a : float 1 + a description + b : float 2 + b description + c : float 3 + c description + + Remaining description\n""" + + expected = """ + Function description. + + Parameters + ---------- + a : float 1 + a description + b : float 2 + b description + c : float 3 + c description + d : float 6 + d description + + Remaining description\n""" + + assert util._docstringer(original_func_doc,adopted_parameters=adopted_func_doc) == expected + + def test_passon_result(self): + def testfunction_inner(a=None,b=None): + return a+b + + @util.pass_on('inner_result',testfunction_inner) + def testfunction_outer(**kwargs): + return kwargs['inner_result']+";"+kwargs['c']+kwargs['d'] + assert testfunction_outer(a='1',b='2',c='3',d='4',e='5') == '12;34' + + def test_passon_signature(self): + def testfunction_inner(a='1',b='2'): + return a+b + + def testfunction_extra(e='5',f='6'): + return e+f + + @util.pass_on('inner_result', testfunction_inner, wrapped=testfunction_extra) + def testfunction_outer(**kwargs): + return kwargs['inner_result']+";"+kwargs['c']+kwargs['d'] + assert [(param.name, param.default) for param in testfunction_outer.__signature__.parameters.values()] == \ + [('a', '1'), ('b', '2'), ('e', '5'), ('f', '6')] + + def test_passon_help(self): + def testfunction_inner(a=None,b=None): + return a+b + + def testfunction_extra(*,c=None,d=None): + return c+d + + @util.pass_on('inner_result', testfunction_inner, wrapped=testfunction_extra) + def testfunction_outer(**kwargs) -> int: + return kwargs['inner_result']+kwargs['c']+kwargs['d'] + + assert pydoc.render_doc(testfunction_outer, renderer=pydoc.plaintext).split("\n")[-2] ==\ + 'testfunction_outer(*, a=None, b=None, c=None, d=None) -> int' diff --git a/src/CLI.f90 b/src/CLI.f90 index a6a70b2e9..aba6e542f 100644 --- a/src/CLI.f90 +++ b/src/CLI.f90 @@ -5,9 +5,8 @@ !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief Parse command line interface for PETSc-based solvers !-------------------------------------------------------------------------------------------------- -#define PETSC_MAJOR 3 #define PETSC_MINOR_MIN 12 -#define PETSC_MINOR_MAX 18 +#define PETSC_MINOR_MAX 19 module CLI use, intrinsic :: ISO_fortran_env @@ -131,7 +130,7 @@ subroutine CLI_init print'(a)', ' Make sure the file "material.yaml" exists in the working' print'(a)', ' directory.' print'(a)', ' For further configuration place "numerics.yaml"' - print'(a)',' and "debug.yaml" in that directory.' + print'(a)',' in that directory.' print'(/,a)',' --restart N' print'(a)', ' Reads in increment N and continues with calculating' print'(a)', ' increment N+1, N+2, ... based on this.' diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0a95fa23..2cf442bf8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,12 +13,15 @@ if(PROJECT_NAME STREQUAL "damask-grid") elseif(PROJECT_NAME STREQUAL "damask-mesh") set(executable-name "DAMASK_mesh") file(GLOB solver-sources CONFIGURE_DEPENDS mesh/*.f90) +elseif(PROJECT_NAME STREQUAL "damask-test") + set(executable-name "DAMASK_test") + file(GLOB solver-sources CONFIGURE_DEPENDS test/*.f90) endif() foreach(solver-source ${solver-sources}) file(READ ${solver-source} content) string(FIND "${content}" "CHKERR" found) - if(NOT ${found} EQUAL -1) + if((NOT ${found} EQUAL -1) AND (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")) set_source_files_properties(${solver-source} PROPERTIES COMPILE_FLAGS "-ffree-line-length-none") endif() endforeach() diff --git a/src/C_routines.c b/src/C_routines.c index 37364543d..26d704974 100644 --- a/src/C_routines.c +++ b/src/C_routines.c @@ -86,7 +86,7 @@ void inflate_c(const uLong *s_deflated, const uLong *s_inflated, const Byte defl } #ifdef FYAML -void to_flow_c(char **flow, int* length_flow, const char *mixed){ +void to_flow_c(char **flow, long* length_flow, const char *mixed){ struct fy_document *fyd = NULL; enum fy_emitter_cfg_flags emit_flags = FYECF_MODE_FLOW_ONELINE | FYECF_STRIP_LABELS | FYECF_STRIP_TAGS |FYECF_STRIP_DOC; @@ -102,7 +102,7 @@ void to_flow_c(char **flow, int* length_flow, const char *mixed){ } *flow = fy_emit_document_to_string(fyd,emit_flags); - *length_flow = strlen(*flow); + *length_flow = (long) strlen(*flow); fy_document_destroy(fyd); } diff --git a/src/HDF5_utilities.f90 b/src/HDF5_utilities.f90 index a87046c5a..936b224e8 100644 --- a/src/HDF5_utilities.f90 +++ b/src/HDF5_utilities.f90 @@ -3,6 +3,7 @@ !> @author Yi-Chin Yang, Max-Planck-Institut für Eisenforschung GmbH !> @author Jennifer Nastola, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @author Philip Eisenlohr, Michigan State University !-------------------------------------------------------------------------------------------------- module HDF5_utilities use HDF5 @@ -17,6 +18,7 @@ module HDF5_utilities use prec use parallelization + use misc #if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY) implicit none(type,external) @@ -26,7 +28,7 @@ module HDF5_utilities private !-------------------------------------------------------------------------------------------------- -!> @brief reads integer or float data of defined shape from file +!> @brief Read integer or float data of defined shape from file. !> @details for parallel IO, all dimension except for the last need to match !-------------------------------------------------------------------------------------------------- interface HDF5_read @@ -48,7 +50,7 @@ module HDF5_utilities end interface HDF5_read !-------------------------------------------------------------------------------------------------- -!> @brief writes integer or real data of defined shape to file +!> @brief Write integer or real data of defined shape to file. !> @details for parallel IO, all dimension except for the last need to match !-------------------------------------------------------------------------------------------------- interface HDF5_write @@ -74,7 +76,7 @@ module HDF5_utilities end interface HDF5_write !-------------------------------------------------------------------------------------------------- -!> @brief attached attributes of type char, integer or real to a file/dataset/group +!> @brief Attach attribute of type char, integer, or real to a file/dataset/group. !-------------------------------------------------------------------------------------------------- interface HDF5_addAttribute module procedure HDF5_addAttribute_str @@ -94,6 +96,7 @@ module HDF5_utilities public :: & HDF5_utilities_init, & + HDF5_chkerr, & HDF5_read, & HDF5_write, & HDF5_write_str, & @@ -110,58 +113,71 @@ contains !-------------------------------------------------------------------------------------------------- -!> @brief initialize HDF5 libary and do sanity checks +!> @brief Initialize HDF5 libary and perform sanity checks. !-------------------------------------------------------------------------------------------------- -subroutine HDF5_utilities_init +subroutine HDF5_utilities_init() integer :: hdferr, HDF5_major, HDF5_minor, HDF5_release, configFlags logical :: avail integer(SIZE_T) :: typeSize - print'(/,1x,a)', '<<<+- HDF5_Utilities init -+>>>' + print'(/,1x,a)', '<<<+- HDF5_utilities init -+>>>' call H5Open_f(hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tget_size_f(H5T_NATIVE_INTEGER,typeSize, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) if (int(bit_size(0),SIZE_T)/=typeSize*8) & error stop 'Default integer size does not match H5T_NATIVE_INTEGER' call H5Tget_size_f(H5T_NATIVE_DOUBLE,typeSize, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) if (int(storage_size(0.0_pReal),SIZE_T)/=typeSize*8) & error stop 'pReal does not match H5T_NATIVE_DOUBLE' call H5get_libversion_f(HDF5_major,HDF5_minor,HDF5_release,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) compression_possible = (HDF5_major == 1 .and. HDF5_minor >= 12) ! https://forum.hdfgroup.org/t/6186 call H5Zfilter_avail_f(H5Z_FILTER_DEFLATE_F,avail,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) compression_possible = compression_possible .and. avail if (avail) then call H5Zget_filter_info_f(H5Z_FILTER_DEFLATE_F,configFlags,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) compression_possible = compression_possible .and. iand(H5Z_FILTER_ENCODE_ENABLED_F,configFlags) > 0 end if call H5Zfilter_avail_f(H5Z_FILTER_SHUFFLE_F,avail,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) compression_possible = compression_possible .and. avail if (avail) then call H5Zget_filter_info_f(H5Z_FILTER_SHUFFLE_F,configFlags,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) compression_possible = compression_possible .and. iand(H5Z_FILTER_ENCODE_ENABLED_F,configFlags) > 0 end if end subroutine HDF5_utilities_init +!-------------------------------------------------------------------------------------------------- +!> @brief Check for HDF5 error. +!-------------------------------------------------------------------------------------------------- +subroutine HDF5_chkerr(e) + + integer, intent(in) :: e + + + if (e<0) error stop 'HDF5 error' + +end subroutine HDF5_chkerr + + !-------------------------------------------------------------------------------------------------- !> @brief Open and initialize HDF5 file. !-------------------------------------------------------------------------------------------------- @@ -176,51 +192,42 @@ integer(HID_T) function HDF5_openFile(fileName,mode,parallel) integer :: hdferr - if (present(mode)) then - m = mode - else - m = 'r' - end if + m = misc_optional(mode,'r') call H5Pcreate_f(H5P_FILE_ACCESS_F, plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #ifdef PETSC - if (present(parallel)) then + if (misc_optional(parallel,.true.)) & #if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY) - if (parallel) call H5Pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL_F90, hdferr) - else call H5Pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL_F90, hdferr) #else - if (parallel) call H5Pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL, hdferr) - else - call H5Pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL, hdferr) + call H5Pset_fapl_mpio_f(plist_id, PETSC_COMM_WORLD, MPI_INFO_NULL, hdferr) #endif - end if - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #endif - if (m == 'w') then + if (m == 'w') then call H5Fcreate_f(fileName,H5F_ACC_TRUNC_F,HDF5_openFile,hdferr,access_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) elseif (m == 'a') then call H5Fopen_f(fileName,H5F_ACC_RDWR_F,HDF5_openFile,hdferr,access_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) elseif (m == 'r') then call H5Fopen_f(fileName,H5F_ACC_RDONLY_F,HDF5_openFile,hdferr,access_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) else error stop 'unknown access mode' end if call H5Pclose_f(plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end function HDF5_openFile !-------------------------------------------------------------------------------------------------- -!> @brief close the opened HDF5 output file +!> @brief Close an open HDF5 file. !-------------------------------------------------------------------------------------------------- subroutine HDF5_closeFile(fileHandle) @@ -229,13 +236,13 @@ subroutine HDF5_closeFile(fileHandle) integer :: hdferr call H5Fclose_f(fileHandle,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_closeFile !-------------------------------------------------------------------------------------------------- -!> @brief adds a new group to the fileHandle +!> @brief Add a new group to the file. !-------------------------------------------------------------------------------------------------- integer(HID_T) function HDF5_addGroup(fileHandle,groupName) @@ -248,19 +255,19 @@ integer(HID_T) function HDF5_addGroup(fileHandle,groupName) !------------------------------------------------------------------------------------------------- ! creating a property list for data access properties call H5Pcreate_f(H5P_GROUP_ACCESS_F, aplist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !------------------------------------------------------------------------------------------------- ! setting I/O mode to collective #ifdef PETSC call H5Pset_all_coll_metadata_ops_f(aplist_id, .true., hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #endif !------------------------------------------------------------------------------------------------- ! Create group call H5Gcreate_f(fileHandle, trim(groupName), HDF5_addGroup, hdferr, OBJECT_NAMELEN_DEFAULT_F,gapl_id = aplist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pclose_f(aplist_id,hdferr) @@ -268,7 +275,7 @@ end function HDF5_addGroup !-------------------------------------------------------------------------------------------------- -!> @brief open an existing group of a file +!> @brief Open an existing group in a file. !-------------------------------------------------------------------------------------------------- integer(HID_T) function HDF5_openGroup(fileHandle,groupName) @@ -284,19 +291,19 @@ integer(HID_T) function HDF5_openGroup(fileHandle,groupName) !------------------------------------------------------------------------------------------------- ! creating a property list for data access properties call H5Pcreate_f(H5P_GROUP_ACCESS_F, aplist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !------------------------------------------------------------------------------------------------- ! setting I/O mode to collective #ifdef PETSC call H5Pget_all_coll_metadata_ops_f(aplist_id, is_collective, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #endif !------------------------------------------------------------------------------------------------- ! opening the group call H5Gopen_f(fileHandle, trim(groupName), HDF5_openGroup, hdferr, gapl_id = aplist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pclose_f(aplist_id,hdferr) @@ -304,7 +311,7 @@ end function HDF5_openGroup !-------------------------------------------------------------------------------------------------- -!> @brief close a group +!> @brief Close a group. !-------------------------------------------------------------------------------------------------- subroutine HDF5_closeGroup(group_id) @@ -313,7 +320,7 @@ subroutine HDF5_closeGroup(group_id) integer :: hdferr call H5Gclose_f(group_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_closeGroup @@ -330,18 +337,14 @@ logical function HDF5_objectExists(loc_id,path) character(len=:), allocatable :: p - if (present(path)) then - p = trim(path) - else - p = '.' - end if + p = trim(misc_optional(path,'.')) call H5Lexists_f(loc_id, p, HDF5_objectExists, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) if (HDF5_objectExists) then call H5Oexists_by_name_f(loc_id, p, HDF5_objectExists, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if end function HDF5_objectExists @@ -364,34 +367,30 @@ subroutine HDF5_addAttribute_str(loc_id,attrLabel,attrValue,path) type(C_PTR), target, dimension(1) :: ptr - if (present(path)) then - p = trim(path) - else - p = '.' - end if + p = trim(misc_optional(path,'.')) attrValue_(1) = trim(attrValue)//C_NULL_CHAR ptr(1) = c_loc(attrValue_(1)) call H5Screate_f(H5S_SCALAR_F,space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) - call H5Aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Aexists_by_name_f(loc_id,p,attrLabel,attrExists,hdferr) + call HDF5_chkerr(hdferr) if (attrExists) then - call H5Adelete_by_name_f(loc_id, trim(p), attrLabel, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Adelete_by_name_f(loc_id,p,attrLabel,hdferr) + call HDF5_chkerr(hdferr) end if - call H5Acreate_by_name_f(loc_id,trim(p),trim(attrLabel),H5T_STRING,space_id,attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Acreate_by_name_f(loc_id,p,trim(attrLabel),H5T_STRING,space_id,attr_id,hdferr) + call HDF5_chkerr(hdferr) call H5Awrite_f(attr_id, H5T_STRING, c_loc(ptr), hdferr) ! ptr instead of c_loc(ptr) works on gfortran, not on ifort - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Aclose_f(attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_addAttribute_str @@ -412,31 +411,27 @@ subroutine HDF5_addAttribute_int(loc_id,attrLabel,attrValue,path) character(len=:), allocatable :: p - if (present(path)) then - p = trim(path) - else - p = '.' - end if + p = trim(misc_optional(path,'.')) call H5Screate_f(H5S_SCALAR_F,space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) - call H5Aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Aexists_by_name_f(loc_id,p,attrLabel,attrExists,hdferr) + call HDF5_chkerr(hdferr) if (attrExists) then - call H5Adelete_by_name_f(loc_id, trim(p), attrLabel, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Adelete_by_name_f(loc_id,p,attrLabel,hdferr) + call HDF5_chkerr(hdferr) end if - call H5Acreate_by_name_f(loc_id,trim(p),trim(attrLabel),H5T_NATIVE_INTEGER,space_id,attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Acreate_by_name_f(loc_id,p,trim(attrLabel),H5T_NATIVE_INTEGER,space_id,attr_id,hdferr) + call HDF5_chkerr(hdferr) call H5Awrite_f(attr_id, H5T_NATIVE_INTEGER, attrValue, int([1],HSIZE_T), hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Aclose_f(attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_addAttribute_int @@ -457,31 +452,27 @@ subroutine HDF5_addAttribute_real(loc_id,attrLabel,attrValue,path) character(len=:), allocatable :: p - if (present(path)) then - p = trim(path) - else - p = '.' - end if + p = trim(misc_optional(path,'.')) call H5Screate_f(H5S_SCALAR_F,space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) - call H5Aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Aexists_by_name_f(loc_id,p,attrLabel,attrExists,hdferr) + call HDF5_chkerr(hdferr) if (attrExists) then - call H5Adelete_by_name_f(loc_id, trim(p), attrLabel, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Adelete_by_name_f(loc_id,p,attrLabel,hdferr) + call HDF5_chkerr(hdferr) end if - call H5Acreate_by_name_f(loc_id,trim(p),trim(attrLabel),H5T_NATIVE_DOUBLE,space_id,attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Acreate_by_name_f(loc_id,p,trim(attrLabel),H5T_NATIVE_DOUBLE,space_id,attr_id,hdferr) + call HDF5_chkerr(hdferr) call H5Awrite_f(attr_id, H5T_NATIVE_DOUBLE, attrValue, int([1],HSIZE_T), hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Aclose_f(attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_addAttribute_real @@ -504,11 +495,7 @@ subroutine HDF5_addAttribute_str_array(loc_id,attrLabel,attrValue,path) type(C_PTR), target, dimension(size(attrValue)) :: ptr - if (present(path)) then - p = trim(path) - else - p = '.' - end if + p = trim(misc_optional(path,'.')) do i=1,size(attrValue) attrValue_(i) = attrValue(i)//C_NULL_CHAR @@ -516,24 +503,24 @@ subroutine HDF5_addAttribute_str_array(loc_id,attrLabel,attrValue,path) end do call H5Screate_simple_f(1,shape(attrValue_,kind=HSIZE_T),space_id,hdferr,shape(attrValue_,kind=HSIZE_T)) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) - call H5Aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Aexists_by_name_f(loc_id,p,attrLabel,attrExists,hdferr) + call HDF5_chkerr(hdferr) if (attrExists) then - call H5Adelete_by_name_f(loc_id, trim(p), attrLabel, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Adelete_by_name_f(loc_id,p,attrLabel,hdferr) + call HDF5_chkerr(hdferr) end if - call H5Acreate_by_name_f(loc_id,trim(p),trim(attrLabel),H5T_STRING,space_id,attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Acreate_by_name_f(loc_id,p,trim(attrLabel),H5T_STRING,space_id,attr_id,hdferr) + call HDF5_chkerr(hdferr) call H5Awrite_f(attr_id, H5T_STRING, c_loc(ptr), hdferr) ! ptr instead of c_loc(ptr) works on gfortran, not on ifort - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Aclose_f(attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_addAttribute_str_array @@ -555,33 +542,29 @@ subroutine HDF5_addAttribute_int_array(loc_id,attrLabel,attrValue,path) character(len=:), allocatable :: p - if (present(path)) then - p = trim(path) - else - p = '.' - end if + p = trim(misc_optional(path,'.')) array_size = size(attrValue,kind=HSIZE_T) call H5Screate_simple_f(1, array_size, space_id, hdferr, array_size) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) - call H5Aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Aexists_by_name_f(loc_id,p,attrLabel,attrExists,hdferr) + call HDF5_chkerr(hdferr) if (attrExists) then - call H5Adelete_by_name_f(loc_id, trim(p), attrLabel, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Adelete_by_name_f(loc_id,p,attrLabel,hdferr) + call HDF5_chkerr(hdferr) end if - call H5Acreate_by_name_f(loc_id,trim(p),trim(attrLabel),H5T_NATIVE_INTEGER,space_id,attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Acreate_by_name_f(loc_id,p,trim(attrLabel),H5T_NATIVE_INTEGER,space_id,attr_id,hdferr) + call HDF5_chkerr(hdferr) call H5Awrite_f(attr_id, H5T_NATIVE_INTEGER, attrValue, array_size, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Aclose_f(attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_addAttribute_int_array @@ -603,33 +586,29 @@ subroutine HDF5_addAttribute_real_array(loc_id,attrLabel,attrValue,path) character(len=:), allocatable :: p - if (present(path)) then - p = trim(path) - else - p = '.' - end if + p = trim(misc_optional(path,'.')) array_size = size(attrValue,kind=HSIZE_T) call H5Screate_simple_f(1, array_size, space_id, hdferr, array_size) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) - call H5Aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Aexists_by_name_f(loc_id,p,attrLabel,attrExists,hdferr) + call HDF5_chkerr(hdferr) if (attrExists) then - call H5Adelete_by_name_f(loc_id, trim(p), attrLabel, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Adelete_by_name_f(loc_id,p,attrLabel,hdferr) + call HDF5_chkerr(hdferr) end if - call H5Acreate_by_name_f(loc_id,trim(p),trim(attrLabel),H5T_NATIVE_DOUBLE,space_id,attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call H5Acreate_by_name_f(loc_id,p,trim(attrLabel),H5T_NATIVE_DOUBLE,space_id,attr_id,hdferr) + call HDF5_chkerr(hdferr) call H5Awrite_f(attr_id, H5T_NATIVE_DOUBLE, attrValue, array_size, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Aclose_f(attr_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(space_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_addAttribute_real_array @@ -645,13 +624,13 @@ subroutine HDF5_setLink(loc_id,target_name,link_name) logical :: linkExists call H5Lexists_f(loc_id, link_name,linkExists, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) if (linkExists) then call H5Ldelete_f(loc_id,link_name, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call H5Lcreate_soft_f(target_name, loc_id, link_name, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_setLink @@ -676,18 +655,15 @@ subroutine HDF5_read_real1(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id, aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -713,18 +689,15 @@ subroutine HDF5_read_real2(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -750,18 +723,15 @@ subroutine HDF5_read_real3(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -788,18 +758,15 @@ subroutine HDF5_read_real4(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -826,18 +793,15 @@ subroutine HDF5_read_real5(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -864,18 +828,15 @@ subroutine HDF5_read_real6(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if - if (any(totalShape == 0)) return + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + +if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -902,18 +863,15 @@ subroutine HDF5_read_real7(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -940,18 +898,15 @@ subroutine HDF5_read_int1(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if - if (any(totalShape == 0)) return + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + +if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -978,18 +933,15 @@ subroutine HDF5_read_int2(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -1015,18 +967,15 @@ subroutine HDF5_read_int3(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -1052,18 +1001,15 @@ subroutine HDF5_read_int4(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -1089,18 +1035,15 @@ subroutine HDF5_read_int5(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -1127,18 +1070,15 @@ subroutine HDF5_read_int6(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -1165,18 +1105,15 @@ subroutine HDF5_read_int7(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel) - else - call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & - myStart, totalShape, loc_id,myShape,datasetName,parallel_default) - end if + call initialize_read(dset_id,filespace_id,memspace_id,plist_id,aplist_id, & + myStart,totalShape,loc_id,myShape,datasetName, & + misc_optional(parallel,parallel_default)) + if (any(totalShape == 0)) return call H5Dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -1207,18 +1144,14 @@ subroutine HDF5_write_real1(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1248,18 +1181,14 @@ subroutine HDF5_write_real2(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1289,18 +1218,14 @@ subroutine HDF5_write_real3(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1330,18 +1255,14 @@ subroutine HDF5_write_real4(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1372,18 +1293,14 @@ subroutine HDF5_write_real5(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1413,18 +1330,14 @@ subroutine HDF5_write_real6(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1454,18 +1367,14 @@ subroutine HDF5_write_real7(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1497,13 +1406,9 @@ subroutine HDF5_write_real(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then select rank(dataset) @@ -1529,7 +1434,7 @@ subroutine HDF5_write_real(dataset,loc_id,datasetName,parallel) call H5Dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) end select - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1550,59 +1455,59 @@ subroutine HDF5_write_str(dataset,loc_id,datasetName) integer(HID_T) :: filetype_id, memtype_id, space_id, dataset_id, dcpl integer :: hdferr - character(len=len_trim(dataset),kind=C_CHAR), target :: dataset_ + character(len=len_trim(dataset,pI64),kind=C_CHAR), target :: dataset_ dataset_ = trim(dataset) call H5Tcopy_f(H5T_C_S1, filetype_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' - call H5Tset_size_f(filetype_id, int(len(dataset_)+1,HSIZE_T), hdferr) ! +1 for NULL - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) + call H5Tset_size_f(filetype_id, len(dataset_,SIZE_T)+1_SIZE_T, hdferr) ! +1 for NULL + call HDF5_chkerr(hdferr) call H5Tcopy_f(H5T_FORTRAN_S1, memtype_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' - call H5Tset_size_f(memtype_id, int(len(dataset_),HSIZE_T), hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) + call H5Tset_size_f(memtype_id, len(dataset_,SIZE_T), hdferr) + call HDF5_chkerr(hdferr) call H5Pcreate_f(H5P_DATASET_CREATE_F, dcpl, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pset_chunk_f(dcpl, 1, [1_HSIZE_T], hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pset_Fletcher32_f(dcpl,hdferr) - if (hdferr < 0) error stop 'HDF5 error' - if (compression_possible .and. len(dataset) > 1024*256) then + call HDF5_chkerr(hdferr) + if (compression_possible .and. len(dataset,pI64) > 1024_pI64*256_pI64) then call H5Pset_shuffle_f(dcpl, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pset_deflate_f(dcpl, 6, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call H5Screate_simple_f(1, [1_HSIZE_T], space_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) CALL H5Dcreate_f(loc_id, datasetName, filetype_id, space_id, dataset_id, hdferr, dcpl) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dwrite_f(dataset_id, memtype_id, c_loc(dataset_(1:1)), hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pclose_f(dcpl, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dclose_f(dataset_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(space_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(memtype_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(filetype_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine HDF5_write_str #if defined(__GFORTRAN__) !-------------------------------------------------------------------------------------------------- -!> @brief write dataset of type integer with 1 dimension +!> @brief Write dataset of type integer with 1 dimensions. !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int1(dataset,loc_id,datasetName,parallel) @@ -1624,18 +1529,14 @@ subroutine HDF5_write_int1(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_INTEGER, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_INTEGER,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1643,7 +1544,7 @@ subroutine HDF5_write_int1(dataset,loc_id,datasetName,parallel) end subroutine HDF5_write_int1 !-------------------------------------------------------------------------------------------------- -!> @brief write dataset of type integer with 2 dimensions +!> @brief Write dataset of type integer with 2 dimensions. !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int2(dataset,loc_id,datasetName,parallel) @@ -1665,18 +1566,14 @@ subroutine HDF5_write_int2(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_INTEGER, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_INTEGER,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1684,7 +1581,7 @@ subroutine HDF5_write_int2(dataset,loc_id,datasetName,parallel) end subroutine HDF5_write_int2 !-------------------------------------------------------------------------------------------------- -!> @brief write dataset of type integer with 3 dimensions +!> @brief Write dataset of type integer with 3 dimensions. !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int3(dataset,loc_id,datasetName,parallel) @@ -1706,18 +1603,14 @@ subroutine HDF5_write_int3(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_INTEGER, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_INTEGER,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1725,7 +1618,7 @@ subroutine HDF5_write_int3(dataset,loc_id,datasetName,parallel) end subroutine HDF5_write_int3 !-------------------------------------------------------------------------------------------------- -!> @brief write dataset of type integer with 4 dimensions +!> @brief Write dataset of type integer with 4 dimensions. !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int4(dataset,loc_id,datasetName,parallel) @@ -1747,18 +1640,14 @@ subroutine HDF5_write_int4(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_INTEGER, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_INTEGER,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1766,7 +1655,7 @@ subroutine HDF5_write_int4(dataset,loc_id,datasetName,parallel) end subroutine HDF5_write_int4 !-------------------------------------------------------------------------------------------------- -!> @brief write dataset of type integer with 5 dimensions +!> @brief Write dataset of type integer with 5 dimensions. !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int5(dataset,loc_id,datasetName,parallel) @@ -1788,18 +1677,14 @@ subroutine HDF5_write_int5(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_INTEGER, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_INTEGER,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1807,7 +1692,7 @@ subroutine HDF5_write_int5(dataset,loc_id,datasetName,parallel) end subroutine HDF5_write_int5 !-------------------------------------------------------------------------------------------------- -!> @brief write dataset of type integer with 6 dimensions +!> @brief Write dataset of type integer with 6 dimensions. !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int6(dataset,loc_id,datasetName,parallel) @@ -1829,18 +1714,14 @@ subroutine HDF5_write_int6(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_INTEGER, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_INTEGER,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1848,7 +1729,7 @@ subroutine HDF5_write_int6(dataset,loc_id,datasetName,parallel) end subroutine HDF5_write_int6 !-------------------------------------------------------------------------------------------------- -!> @brief write dataset of type integer with 7 dimensions +!> @brief Write dataset of type integer with 7 dimensions. !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int7(dataset,loc_id,datasetName,parallel) @@ -1870,18 +1751,14 @@ subroutine HDF5_write_int7(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_INTEGER, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then call H5Dwrite_f(dset_id, H5T_NATIVE_INTEGER,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1891,7 +1768,7 @@ end subroutine HDF5_write_int7 #else !-------------------------------------------------------------------------------------------------- -!> @brief write dataset of type integer with 1-7 dimension +!> @brief Write dataset of type integer with 1-7 dimensions. !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int(dataset,loc_id,datasetName,parallel) @@ -1913,13 +1790,9 @@ subroutine HDF5_write_int(dataset,loc_id,datasetName,parallel) myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - if (present(parallel)) then - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel) - else - call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & - myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_INTEGER,parallel_default) - end if + call initialize_write(dset_id,filespace_id,memspace_id,plist_id, & + myStart,totalShape,loc_id,myShape,datasetName,H5T_NATIVE_INTEGER, & + misc_optional(parallel,parallel_default)) if (product(totalShape) /= 0) then select rank(dataset) @@ -1945,7 +1818,7 @@ subroutine HDF5_write_int(dataset,loc_id,datasetName,parallel) call H5Dwrite_f(dset_id, H5T_NATIVE_INTEGER,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) end select - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if call finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -1954,7 +1827,7 @@ end subroutine HDF5_write_int #endif !-------------------------------------------------------------------------------------------------- -!> @brief initialize HDF5 handles, determines global shape and start for parallel read +!> @brief Initialize read handles and determine global shape in case of parallel IO. !-------------------------------------------------------------------------------------------------- subroutine initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, globalShape, & @@ -1978,7 +1851,7 @@ subroutine initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_ !------------------------------------------------------------------------------------------------- ! creating a property list for transfer properties (is collective for MPI) call H5Pcreate_f(H5P_DATASET_XFER_F, plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- readSize = 0_MPI_INTEGER_KIND @@ -1986,7 +1859,7 @@ subroutine initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_ #ifdef PETSC if (parallel) then call H5Pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call MPI_Allreduce(MPI_IN_PLACE,readSize,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI) ! get total output size over each process if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' end if @@ -1997,41 +1870,41 @@ subroutine initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_ if (any(globalShape == 0)) then call H5Pclose_f(plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) return end if !-------------------------------------------------------------------------------------------------- ! create dataspace in memory (local shape) call H5Screate_simple_f(size(localShape), localShape, memspace_id, hdferr, localShape) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! creating a property list for IO and set it to collective call H5Pcreate_f(H5P_DATASET_ACCESS_F, aplist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #ifdef PETSC call H5Pset_all_coll_metadata_ops_f(aplist_id, .true., hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #endif !-------------------------------------------------------------------------------------------------- ! open the dataset in the file and get the space ID call H5Dopen_f(loc_id,datasetName,dset_id,hdferr, dapl_id = aplist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dget_space_f(dset_id, filespace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! select a hyperslab (the portion of the current process) in the file call H5Sselect_hyperslab_f(filespace_id, H5S_SELECT_SET_F, myStart, localShape, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine initialize_read !-------------------------------------------------------------------------------------------------- -!> @brief closes HDF5 handles +!> @brief Close read handles. !-------------------------------------------------------------------------------------------------- subroutine finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) @@ -2039,21 +1912,21 @@ subroutine finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id integer :: hdferr call H5Pclose_f(plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pclose_f(aplist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dclose_f(dset_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(filespace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(memspace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine finalize_read !-------------------------------------------------------------------------------------------------- -!> @brief initialize HDF5 handles, determines global shape and start for parallel write +!> @brief Initialize write handles and determine global shape in case of parallel IO. !-------------------------------------------------------------------------------------------------- subroutine initialize_write(dset_id, filespace_id, memspace_id, plist_id, & myStart, totalShape, & @@ -2080,11 +1953,11 @@ subroutine initialize_write(dset_id, filespace_id, memspace_id, plist_id, & !------------------------------------------------------------------------------------------------- ! creating a property list for transfer properties (is collective when writing in parallel) call H5Pcreate_f(H5P_DATASET_XFER_F, plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #ifdef PETSC if (parallel) then call H5Pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if #endif @@ -2105,47 +1978,47 @@ subroutine initialize_write(dset_id, filespace_id, memspace_id, plist_id, & !-------------------------------------------------------------------------------------------------- ! chunk dataset, enable compression for larger datasets call H5Pcreate_f(H5P_DATASET_CREATE_F, dcpl, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) if (product(totalShape) > 0) then call H5Pset_Fletcher32_f(dcpl,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) if (product(totalShape) >= chunkSize*2_HSIZE_T) then call H5Pset_chunk_f(dcpl, size(totalShape), getChunks(totalShape,chunkSize), hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) if (compression_possible) then call H5Pset_shuffle_f(dcpl, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pset_deflate_f(dcpl, 6, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if else call H5Pset_chunk_f(dcpl, size(totalShape), totalShape, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end if end if !-------------------------------------------------------------------------------------------------- ! create dataspace in memory (local shape) and in file (global shape) call H5Screate_simple_f(size(myShape), myShape, memspace_id, hdferr, myShape) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Screate_simple_f(size(totalShape), totalShape, filespace_id, hdferr, totalShape) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! create dataset in the file and select a hyperslab from it (the portion of the current process) call H5Dcreate_f(loc_id, trim(datasetName), datatype, filespace_id, dset_id, hdferr, dcpl) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sselect_hyperslab_f(filespace_id, H5S_SELECT_SET_F, myStart, myShape, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Pclose_f(dcpl , hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) contains !------------------------------------------------------------------------------------------------ - !> @brief determine chunk layout + !> @brief Determine chunk layout. !------------------------------------------------------------------------------------------------ pure function getChunks(totalShape,chunkSize) @@ -2162,7 +2035,7 @@ end subroutine initialize_write !-------------------------------------------------------------------------------------------------- -!> @brief closes HDF5 handles +!> @brief Closes write handles. !-------------------------------------------------------------------------------------------------- subroutine finalize_write(plist_id, dset_id, filespace_id, memspace_id) @@ -2170,13 +2043,13 @@ subroutine finalize_write(plist_id, dset_id, filespace_id, memspace_id) integer :: hdferr call H5Pclose_f(plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dclose_f(dset_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(filespace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(memspace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) end subroutine finalize_write diff --git a/src/IO.f90 b/src/IO.f90 index c83ea1a22..882b7faf6 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -11,6 +11,7 @@ module IO IO_STDERR => ERROR_UNIT use prec + use misc implicit none(type,external) private @@ -30,6 +31,7 @@ module IO IO_read, & IO_readlines, & IO_isBlank, & + IO_wrapLines, & IO_stringPos, & IO_stringValue, & IO_intValue, & @@ -136,8 +138,8 @@ function IO_read(fileName) result(fileContent) if (myStat /= 0) call IO_error(102,trim(fileName)) close(fileUnit) - if (scan(fileContent(:index(fileContent,LF)),CR//LF) /= 0) fileContent = CRLF2LF(fileContent) - if (fileContent(fileLength:fileLength) /= IO_EOL) fileContent = fileContent//IO_EOL ! ensure EOL@EOF + if (index(fileContent,CR//LF,kind=pI64) /= 0) fileContent = CRLF2LF(fileContent) + if (fileContent(fileLength:fileLength) /= IO_EOL) fileContent = fileContent//IO_EOL ! ensure EOL@EOF end function IO_read @@ -158,6 +160,51 @@ logical pure function IO_isBlank(string) end function IO_isBlank +!-------------------------------------------------------------------------------------------------- +!> @brief Insert EOL at separator trying to keep line length below limit. +!-------------------------------------------------------------------------------------------------- +function IO_wrapLines(string,separator,filler,length) + + character(len=*), intent(in) :: string !< string to split + character, optional, intent(in) :: separator !< line breaks are possible after this character, defaults to ',' + character(len=*), optional, intent(in) :: filler !< character(s) to insert after line break, defaults to none + integer, optional, intent(in) :: length !< (soft) line limit, defaults to 80 + character(len=:), allocatable :: IO_wrapLines + + integer, dimension(:), allocatable :: pos_sep, pos_split + integer :: i,s,e + + + i = index(string,misc_optional(separator,',')) + if (i == 0) then + IO_wrapLines = string + else + pos_sep = [0] + s = i + do while (i /= 0 .and. s < len(string)) + pos_sep = [pos_sep,s] + i = index(string(s+1:),misc_optional(separator,',')) + s = s + i + end do + pos_sep = [pos_sep,len(string)] + + pos_split = emptyIntArray + s = 1 + e = 2 + IO_wrapLines = '' + do while (e < size(pos_sep)) + if (pos_sep(e+1) - pos_sep(s) >= misc_optional(length,80)) then + IO_wrapLines = IO_wrapLines//adjustl(string(pos_sep(s)+1:pos_sep(e)))//IO_EOL//misc_optional(filler,'') + s = e + end if + e = e + 1 + end do + IO_wrapLines = IO_wrapLines//adjustl(string(pos_sep(s)+1:)) + end if + +end function IO_wrapLines + + !-------------------------------------------------------------------------------------------------- !> @brief Locate all whitespace-separated chunks in given string and returns array containing !! number them and the left/right position to be used by IO_xxxVal. @@ -484,8 +531,6 @@ subroutine IO_error(error_ID,ext_msg,label1,ID1,label2,ID2) !-------------------------------------------------------------------------------------------------- ! user errors - case (602) - msg = 'invalid selection for debug' case (603) msg = 'invalid data for table' @@ -607,17 +652,17 @@ pure function CRLF2LF(string) character(len=*), intent(in) :: string character(len=:), allocatable :: CRLF2LF - integer :: c,n + integer(pI64) :: c,n - allocate(character(len=len_trim(string))::CRLF2LF) - if (len(CRLF2LF) == 0) return + allocate(character(len=len_trim(string,pI64))::CRLF2LF) + if (len(CRLF2LF,pI64) == 0) return - n = 0 - do c=1, len_trim(string) + n = 0_pI64 + do c=1_pI64, len_trim(string,pI64) CRLF2LF(c-n:c-n) = string(c:c) - if (c == len_trim(string)) exit - if (string(c:c+1) == CR//LF) n = n + 1 + if (c == len_trim(string,pI64)) exit + if (string(c:c+1_pI64) == CR//LF) n = n + 1_pI64 end do CRLF2LF = CRLF2LF(:c-n) @@ -729,6 +774,7 @@ subroutine selfTest() if (CRLF2LF('A'//CR//LF//'B') /= 'A'//LF//'B') error stop 'CRLF2LF/3' if (CRLF2LF('A'//CR//LF//'B'//CR//LF) /= & 'A'//LF//'B'//LF) error stop 'CRLF2LF/4' + if (CRLF2LF('A'//LF//CR//'B') /= 'A'//LF//CR//'B') error stop 'CRLF2LF/5' str=' '; if (.not. IO_isBlank(str)) error stop 'IO_isBlank/1' str=' #isBlank';if (.not. IO_isBlank(str)) error stop 'IO_isBlank/2' @@ -749,6 +795,21 @@ subroutine selfTest() str=' ab #';out=IO_rmComment(str) if (out /= ' ab'.or. len(out) /= 3) error stop 'IO_rmComment/6' + if ('abc, def' /= IO_wrapLines('abc, def')) & + error stop 'IO_wrapLines/1' + if ('abc,'//IO_EOL//'def' /= IO_wrapLines('abc,def',length=3)) & + error stop 'IO_wrapLines/2' + if ('abc,'//IO_EOL//'def' /= IO_wrapLines('abc,def',length=5)) & + error stop 'IO_wrapLines/3' + if ('abc, def' /= IO_wrapLines('abc, def',length=3,separator='.')) & + error stop 'IO_wrapLines/4' + if ('abc.'//IO_EOL//'def' /= IO_wrapLines('abc. def',length=3,separator='.')) & + error stop 'IO_wrapLines/5' + if ('abc,'//IO_EOL//'defg,'//IO_EOL//'hij' /= IO_wrapLines('abc,defg,hij',length=4)) & + error stop 'IO_wrapLines/6' + if ('abc,'//IO_EOL//'xxdefg,'//IO_EOL//'xxhij' /= IO_wrapLines('abc,defg, hij',filler='xx',length=4)) & + error stop 'IO_wrapLines/7' + end subroutine selfTest end module IO diff --git a/src/Marc/DAMASK_Marc.f90 b/src/Marc/DAMASK_Marc.f90 index 024fd410b..92b89c334 100644 --- a/src/Marc/DAMASK_Marc.f90 +++ b/src/Marc/DAMASK_Marc.f90 @@ -142,12 +142,13 @@ end function solverIsSymmetric end module DAMASK_interface #include "../parallelization.f90" +#include "../misc.f90" #include "../constants.f90" #include "../IO.f90" #include "../YAML_types.f90" #include "../YAML_parse.f90" #include "../HDF5_utilities.f90" -#include "../results.f90" +#include "../result.f90" #include "../config.f90" #include "../LAPACK_interface.f90" #include "../math.f90" @@ -282,34 +283,15 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, & logical, save :: & lastIncConverged = .false., & !< needs description outdatedByNewInc = .false., & !< needs description - materialpoint_init_done = .false., & !< remember whether init has been done already - debug_basic = .true. - type(tList), pointer :: & - debug_Marc ! pointer to Marc debug options + materialpoint_init_done = .false. !< remember whether init has been done already - if (debug_basic) then - print'(a,/,i8,i8,i2)', ' MSC.Marc information on shape of element(2), IP:', m, nn - print'(a,2(i1))', ' Jacobian: ', ngens,ngens - print'(a,i1)', ' Direct stress: ', ndi - print'(a,i1)', ' Shear stress: ', nshear - print'(a,i2)', ' DoF: ', ndeg - print'(a,i2)', ' Coordinates: ', ncrd - print'(a,i12)', ' Nodes: ', nnode - print'(a,i1)', ' Deformation gradient: ', itel - write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') ' Deformation gradient at t=n:', & - transpose(ffn) - write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') ' Deformation gradient at t=n+1:', & - transpose(ffn1) - end if defaultNumThreadsInt = omp_get_num_threads() ! remember number of threads set by Marc call omp_set_num_threads(1_pI32) ! no openMP if (.not. materialpoint_init_done) then materialpoint_init_done = .true. - call materialpoint_initAll - debug_Marc => config_debug%get_list('Marc',defaultVal=emptyList) - debug_basic = debug_Marc%contains('basic') + call materialpoint_initAll() end if computationMode = 0 ! save initialization value, since it does not result in any calculation @@ -434,7 +416,7 @@ subroutine uedinc(inc,incsub) end do call discretization_Marc_UpdateNodeAndIpCoords(d_n) - call materialpoint_results(int(inc),cptim) + call materialpoint_result(int(inc),cptim) inc_written = int(inc) end if diff --git a/src/Marc/discretization_Marc.f90 b/src/Marc/discretization_Marc.f90 index 405339b9b..46e9eba45 100644 --- a/src/Marc/discretization_Marc.f90 +++ b/src/Marc/discretization_Marc.f90 @@ -15,7 +15,7 @@ module discretization_Marc use element use discretization use geometry_plastic_nonlocal - use results + use result implicit none(type,external) private @@ -59,8 +59,7 @@ subroutine discretization_Marc_init integer, dimension(:), allocatable :: & materialAt integer:: & - Nelems, & !< total number of elements in the mesh - debug_e, debug_i + Nelems !< total number of elements in the mesh real(pReal), dimension(:,:), allocatable :: & IP_reshaped @@ -75,9 +74,6 @@ subroutine discretization_Marc_init print'(/,a)', ' <<<+- discretization_Marc init -+>>>'; flush(6) - debug_e = config_debug%get_asInt('element',defaultVal=1) - debug_i = config_debug%get_asInt('integrationpoint',defaultVal=1) - num_commercialFEM => config_numerics%get_dict('commercialFEM',defaultVal = emptyDict) mesh_unitlength = num_commercialFEM%get_asFloat('unitlength',defaultVal=1.0_pReal) ! set physical extent of a length unit in mesh if (mesh_unitlength <= 0.0_pReal) call IO_error(301,'unitlength') @@ -85,9 +81,6 @@ subroutine discretization_Marc_init call inputRead(elem,node0_elem,connectivity_elem,materialAt) nElems = size(connectivity_elem,2) - if (debug_e < 1 .or. debug_e > nElems) call IO_error(602,'element') - if (debug_i < 1 .or. debug_i > elem%nIPs) call IO_error(602,'IP') - allocate(cellNodeDefinition(elem%nNodes-1)) allocate(connectivity_cell(elem%NcellNodesPerCell,elem%nIPs,nElems)) @@ -110,7 +103,7 @@ subroutine discretization_Marc_init call geometry_plastic_nonlocal_setIParea(norm2(unscaledNormals,1)) call geometry_plastic_nonlocal_setIPareaNormal(unscaledNormals/spread(norm2(unscaledNormals,1),1,3)) call geometry_plastic_nonlocal_setIPneighborhood(IPneighborhood(elem)) - call geometry_plastic_nonlocal_results + call geometry_plastic_nonlocal_result() end subroutine discretization_Marc_init @@ -167,23 +160,23 @@ subroutine writeGeometry(elem, & coordinates_points - call results_openJobFile - call results_closeGroup(results_addGroup('geometry')) + call result_openJobFile() + call result_closeGroup(result_addGroup('geometry')) - call results_writeDataset(connectivity_elem,'geometry','T_e',& - 'connectivity of the elements','-') + call result_writeDataset(connectivity_elem,'geometry','T_e',& + 'connectivity of the elements','-') - call results_writeDataset(connectivity_cell_reshaped,'geometry','T_c', & - 'connectivity of the cells','-') - call results_addAttribute('VTK_TYPE',elem%vtkType,'geometry/T_c') + call result_writeDataset(connectivity_cell_reshaped,'geometry','T_c', & + 'connectivity of the cells','-') + call result_addAttribute('VTK_TYPE',elem%vtkType,'geometry/T_c') - call results_writeDataset(coordinates_nodes,'geometry','x_n', & - 'initial coordinates of the nodes','m') + call result_writeDataset(coordinates_nodes,'geometry','x_n', & + 'initial coordinates of the nodes','m') - call results_writeDataset(coordinates_points,'geometry','x_p', & - 'initial coordinates of the materialpoints (cell centers)','m') + call result_writeDataset(coordinates_points,'geometry','x_p', & + 'initial coordinates of the materialpoints (cell centers)','m') - call results_closeJobFile + call result_closeJobFile() end subroutine writeGeometry @@ -216,11 +209,11 @@ subroutine inputRead(elem,node0_elem,connectivity_elem,materialAt) mapElemSet !< list of elements in elementSet - call results_openJobFile - call results_writeDataset_str(IO_read(trim(getSolverJobName())//InputFileExtension), 'setup', & + call result_openJobFile() + call result_writeDataset_str(IO_read(trim(getSolverJobName())//InputFileExtension), 'setup', & trim(getSolverJobName())//InputFileExtension, & 'MSC.Marc input deck') - call results_closeJobFile + call result_closeJobFile() inputFile = IO_readlines(trim(getSolverJobName())//InputFileExtension) call inputRead_fileFormat(fileFormatVersion, & diff --git a/src/Marc/materialpoint_Marc.f90 b/src/Marc/materialpoint_Marc.f90 index 2b910217d..01d28ec80 100644 --- a/src/Marc/materialpoint_Marc.f90 +++ b/src/Marc/materialpoint_Marc.f90 @@ -10,7 +10,7 @@ module materialpoint_Marc use YAML_types use YAML_parse use HDF5_utilities - use results + use result use config use math use rotations @@ -50,22 +50,10 @@ module materialpoint_Marc type(tNumerics), private :: num - type, private :: tDebugOptions - logical :: & - basic, & - extensive, & - selective - integer:: & - element, & - ip - end type tDebugOptions - - type(tDebugOptions), private :: debugmaterialpoint - public :: & materialpoint_general, & materialpoint_initAll, & - materialpoint_results + materialpoint_result contains @@ -81,7 +69,7 @@ subroutine materialpoint_initAll() call YAML_types_init() call YAML_parse_init() call HDF5_utilities_init() - call results_init(.false.) + call result_init(.false.) call config_init() call math_init() call rotations_init() @@ -93,42 +81,24 @@ subroutine materialpoint_initAll() call phase_init() call homogenization_init() call materialpoint_init() - call config_deallocate() + call config_material_deallocate() + call config_numerics_deallocate() + end subroutine materialpoint_initAll !-------------------------------------------------------------------------------------------------- -!> @brief allocate the arrays defined in module materialpoint and initialize them +!> @brief Allocate the arrays defined in module materialpoint and initialize them. !-------------------------------------------------------------------------------------------------- subroutine materialpoint_init() - type(tList), pointer :: & - debug_materialpoint - - print'(/,1x,a)', '<<<+- materialpoint init -+>>>'; flush(IO_STDOUT) allocate(materialpoint_cs( 6,discretization_nIPs,discretization_Nelems), source= 0.0_pReal) allocate(materialpoint_dcsdE( 6,6,discretization_nIPs,discretization_Nelems), source= 0.0_pReal) allocate(materialpoint_dcsdE_knownGood(6,6,discretization_nIPs,discretization_Nelems), source= 0.0_pReal) -!------------------------------------------------------------------------------ -! read debug options - - debug_materialpoint => config_debug%get_list('materialpoint',defaultVal=emptyList) - debugmaterialpoint%basic = debug_materialpoint%contains('basic') - debugmaterialpoint%extensive = debug_materialpoint%contains('extensive') - debugmaterialpoint%selective = debug_materialpoint%contains('selective') - debugmaterialpoint%element = config_debug%get_asInt('element',defaultVal = 1) - debugmaterialpoint%ip = config_debug%get_asInt('integrationpoint',defaultVal = 1) - - if (debugmaterialpoint%basic) then - print'(a32,1x,6(i8,1x))', 'materialpoint_cs: ', shape(materialpoint_cs) - print'(a32,1x,6(i8,1x))', 'materialpoint_dcsdE: ', shape(materialpoint_dcsdE) - print'(a32,1x,6(i8,1x),/)', 'materialpoint_dcsdE_knownGood: ', shape(materialpoint_dcsdE_knownGood) - flush(IO_STDOUT) - end if end subroutine materialpoint_init @@ -164,16 +134,6 @@ subroutine materialpoint_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip, elCP = discretization_Marc_FEM2DAMASK_elem(elFE) ce = discretization_Marc_FEM2DAMASK_cell(ip,elFE) - if (debugmaterialpoint%basic .and. elCP == debugmaterialpoint%element .and. ip == debugmaterialpoint%ip) then - print'(/,a)', '#############################################' - print'(a1,a22,1x,i8,a13)', '#','element', elCP, '#' - print'(a1,a22,1x,i8,a13)', '#','ip', ip, '#' - print'(a1,a22,1x,i8,a13)', '#','cycleCounter', cycleCounter, '#' - print'(a1,a22,1x,i8,a13)', '#','computationMode',mode, '#' - if (terminallyIll) & - print'(a,/)', '# --- terminallyIll --- #' - print'(a,/)', '#############################################'; flush (6) - end if if (iand(mode, materialpoint_BACKUPJACOBIAN) /= 0) & materialpoint_dcsde_knownGood = materialpoint_dcsde @@ -194,7 +154,6 @@ subroutine materialpoint_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip, materialpoint_dcsde(1:6,1:6,ip,elCP) = ODD_JACOBIAN * math_eye(6) else validCalculation - if (debugmaterialpoint%extensive) print'(a,i8,1x,i2)', '<< materialpoint >> calculation for elFE ip ',elFE,ip call homogenization_mechanical_response(dt,(elCP-1)*discretization_nIPs + ip,(elCP-1)*discretization_nIPs + ip) if (.not. terminallyIll) & call homogenization_mechanical_response2(dt,[ip,ip],[elCP,elCP]) @@ -232,15 +191,6 @@ subroutine materialpoint_general(mode, ffn, ffn1, temperature_inp, dt, elFE, ip, end if terminalIllness end if validCalculation - if (debugmaterialpoint%extensive & - .and. ((debugmaterialpoint%element == elCP .and. debugmaterialpoint%ip == ip) .or. .not. debugmaterialpoint%selective)) then - print'(a,i8,1x,i2,/,12x,6(f10.3,1x)/)', & - '<< materialpoint >> stress/MPa at elFE ip ', elFE, ip, materialpoint_cs(1:6,ip,elCP)*1.0e-6_pReal - print'(a,i8,1x,i2,/,6(12x,6(f10.3,1x)/))', & - '<< materialpoint >> Jacobian/GPa at elFE ip ', elFE, ip, transpose(materialpoint_dcsdE(1:6,1:6,ip,elCP))*1.0e-9_pReal - flush(IO_STDOUT) - end if - end if if (all(abs(materialpoint_dcsdE(1:6,1:6,ip,elCP)) < 1e-10_pReal)) & @@ -257,8 +207,8 @@ end subroutine materialpoint_general !-------------------------------------------------------------------------------------------------- subroutine materialpoint_forward - call homogenization_forward - call phase_forward + call homogenization_forward() + call phase_forward() end subroutine materialpoint_forward @@ -266,19 +216,19 @@ end subroutine materialpoint_forward !-------------------------------------------------------------------------------------------------- !> @brief Trigger writing of results. !-------------------------------------------------------------------------------------------------- -subroutine materialpoint_results(inc,time) +subroutine materialpoint_result(inc,time) integer, intent(in) :: inc real(pReal), intent(in) :: time - call results_openJobFile - call results_addIncrement(inc,time) - call phase_results - call homogenization_results - call discretization_results - call results_finalizeIncrement - call results_closeJobFile + call result_openJobFile() + call result_addIncrement(inc,time) + call phase_result() + call homogenization_result() + call discretization_result() + call result_finalizeIncrement() + call result_closeJobFile() -end subroutine materialpoint_results +end subroutine materialpoint_result end module materialpoint_Marc diff --git a/src/YAML_parse.f90 b/src/YAML_parse.f90 index b1f5aaf71..1581e8dc0 100644 --- a/src/YAML_parse.f90 +++ b/src/YAML_parse.f90 @@ -1,11 +1,12 @@ !---------------------------------------------------------------------------------------------------- !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Sharan Roongta, Max-Planck-Institut für Eisenforschung GmbH -!> @brief Parser for YAML files -!> @details module converts a YAML input file to an equivalent YAML flow style which is then parsed. +!> @brief Parser for YAML files. +!> @details Module converts a YAML input file to an equivalent YAML flow style which is then parsed. !---------------------------------------------------------------------------------------------------- module YAML_parse use prec + use misc use IO use YAML_types #ifdef FYAML @@ -24,11 +25,11 @@ module YAML_parse interface subroutine to_flow_C(flow,length_flow,mixed) bind(C) - use, intrinsic :: ISO_C_Binding, only: C_INT, C_CHAR, C_PTR + use, intrinsic :: ISO_C_Binding, only: C_LONG, C_CHAR, C_PTR implicit none(type,external) type(C_PTR), intent(out) :: flow - integer(C_INT), intent(out) :: length_flow + integer(C_LONG), intent(out) :: length_flow character(kind=C_CHAR), dimension(*), intent(in) :: mixed end subroutine to_flow_C @@ -54,7 +55,7 @@ end subroutine YAML_parse_init !-------------------------------------------------------------------------------------------------- -!> @brief Parse a YAML string with list as root into a a structure of nodes. +!> @brief Parse a YAML string with list at root into a structure of nodes. !> @details The string needs to end with a newline (unless using libfyaml). !-------------------------------------------------------------------------------------------------- function YAML_parse_str_asList(str) result(list) @@ -72,7 +73,7 @@ end function YAML_parse_str_asList !-------------------------------------------------------------------------------------------------- -!> @brief Parse a YAML string with dict as root into a a structure of nodes. +!> @brief Parse a YAML string with dict at root into a structure of nodes. !> @details The string needs to end with a newline (unless using libfyaml). !-------------------------------------------------------------------------------------------------- function YAML_parse_str_asDict(str) result(dict) @@ -90,38 +91,39 @@ end function YAML_parse_str_asDict !-------------------------------------------------------------------------------------------------- -!> @brief reads the flow style string and stores it in the form of dictionaries, lists and scalars. -!> @details A node type pointer can either point to a dictionary, list or scalar type entities. +!> @brief Read a string in flow style and store it in the form of dictionaries, lists, and scalars. +!> @details A node-type pointer can either point to a dictionary, list, or scalar type entities. !-------------------------------------------------------------------------------------------------- recursive function parse_flow(YAML_flow) result(node) - character(len=*), intent(in) :: YAML_flow !< YAML file in flow style - class(tNode), pointer :: node + character(len=*), intent(in) :: YAML_flow !< YAML file in flow style + class(tNode), pointer :: node - class(tNode), pointer :: & + class(tNode), pointer :: & myVal - character(len=:), allocatable :: & + character(len=:), allocatable :: & flow_string, & key - integer :: & + integer(pI64) :: & e, & ! end position of dictionary or list s, & ! start position of dictionary or list d ! position of key: value separator (':') + flow_string = trim(adjustl(YAML_flow)) - if (len_trim(flow_string) == 0) then + if (len_trim(flow_string,pI64) == 0_pI64) then node => emptyDict return elseif (flow_string(1:1) == '{') then ! start of a dictionary - e = 1 + e = 1_pI64 allocate(tDict::node) - do while (e < len_trim(flow_string)) + do while (e < len_trim(flow_string,pI64)) s = e - d = s + scan(flow_string(s+1:),':') - e = d + find_end(flow_string(d+1:),'}') - key = trim(adjustl(flow_string(s+1:d-1))) + d = s + scan(flow_string(s+1_pI64:),':',kind=pI64) + e = d + find_end(flow_string(d+1_pI64:),'}') + key = trim(adjustl(flow_string(s+1_pI64:d-1_pI64))) if (quotedString(key)) key = key(2:len(key)-1) - myVal => parse_flow(flow_string(d+1:e-1)) ! parse items (recursively) + myVal => parse_flow(flow_string(d+1_pI64:e-1_pI64)) ! parse items (recursively) select type (node) class is (tDict) @@ -129,12 +131,12 @@ recursive function parse_flow(YAML_flow) result(node) end select end do elseif (flow_string(1:1) == '[') then ! start of a list - e = 1 + e = 1_pI64 allocate(tList::node) - do while (e < len_trim(flow_string)) + do while (e < len_trim(flow_string,pI64)) s = e - e = s + find_end(flow_string(s+1:),']') - myVal => parse_flow(flow_string(s+1:e-1)) ! parse items (recursively) + e = s + find_end(flow_string(s+1_pI64:),']') + myVal => parse_flow(flow_string(s+1_pI64:e-1_pI64)) ! parse items (recursively) select type (node) class is (tList) @@ -157,7 +159,7 @@ end function parse_flow !-------------------------------------------------------------------------------------------------- -!> @brief finds location of chunk end: ',' or '}' or ']' +!> @brief Find location of chunk end: ',' '}', or ']'. !> @details leaves nested lists ( '[...]' and dicts '{...}') intact !-------------------------------------------------------------------------------------------------- integer function find_end(str,e_char) @@ -165,21 +167,21 @@ integer function find_end(str,e_char) character(len=*), intent(in) :: str !< chunk of YAML flow string character, intent(in) :: e_char !< end of list/dict ( '}' or ']') - integer :: N_sq, & !< number of open square brackets - N_cu, & !< number of open curly brackets + integer(pI64) :: N_sq, & !< number of open square brackets + N_cu, & !< number of open curly brackets i - N_sq = 0 - N_cu = 0 - i = 1 - do while(i<=len_trim(str)) - if (scan(str(i:i),IO_QUOTES) == 1) i = i + scan(str(i+1:),str(i:i)) - if (N_sq==0 .and. N_cu==0 .and. scan(str(i:i),e_char//',') == 1) exit - N_sq = N_sq + merge(1,0,str(i:i) == '[') - N_cu = N_cu + merge(1,0,str(i:i) == '{') - N_sq = N_sq - merge(1,0,str(i:i) == ']') - N_cu = N_cu - merge(1,0,str(i:i) == '}') - i = i + 1 + N_sq = 0_pI64 + N_cu = 0_pI64 + i = 1_pI64 + do while(i<=len_trim(str,pI64)) + if (scan(str(i:i),IO_QUOTES,kind=pI64) == 1_pI64) i = i + scan(str(i+1:),str(i:i),kind=pI64) + if (N_sq==0 .and. N_cu==0 .and. scan(str(i:i),e_char//',',kind=pI64) == 1_pI64) exit + N_sq = N_sq + merge(1_pI64,0_pI64,str(i:i) == '[') + N_cu = N_cu + merge(1_pI64,0_pI64,str(i:i) == '{') + N_sq = N_sq - merge(1_pI64,0_pI64,str(i:i) == ']') + N_cu = N_cu - merge(1_pI64,0_pI64,str(i:i) == '}') + i = i + 1_pI64 end do find_end = i @@ -187,7 +189,7 @@ end function find_end !-------------------------------------------------------------------------------------------------- -! @brief check whether a string is enclosed with single or double quotes +! @brief Check whether a string is enclosed with single or double quotes. !-------------------------------------------------------------------------------------------------- logical function quotedString(line) @@ -208,7 +210,7 @@ end function quotedString #ifdef FYAML !-------------------------------------------------------------------------------------------------- -! @brief Convert all block style YAML parts to flow style. +! @brief Convert all block-style YAML parts to flow style. !-------------------------------------------------------------------------------------------------- function to_flow(mixed) result(flow) @@ -216,17 +218,17 @@ function to_flow(mixed) result(flow) character(:,C_CHAR), allocatable :: flow type(C_PTR) :: str_ptr - integer(C_INT) :: strlen + integer(C_LONG) :: strlen call to_flow_C(str_ptr,strlen,f_c_string(mixed)) - if (strlen < 1) call IO_error(703,ext_msg='libyfaml') + if (strlen < 1_C_LONG) call IO_error(703,ext_msg='libyfaml') allocate(character(len=strlen,kind=c_char) :: flow) block character(len=strlen,kind=c_char), pointer :: s call c_f_pointer(str_ptr,s) - flow = s(:len(s)-1) + flow = s(:len(s,pI64)-1_pI64) end block call free_C(str_ptr) @@ -236,41 +238,43 @@ end function to_flow #else !-------------------------------------------------------------------------------------------------- -! @brief Determine Indentation. -! @details It determines the indentation level for a given block/line. -! In cases for nested lists, an offset is added to determine the indent of the item block (skip -! leading dashes) +! @brief Determine indentation depth. +! @details Indentation level is determined for a given block/line. +! In case of nested lists, an offset is added to determine the indent of the item block (skip +! leading dashes). !-------------------------------------------------------------------------------------------------- integer function indentDepth(line,offset) character(len=*), intent(in) :: line integer, optional,intent(in) :: offset - indentDepth = verify(line,IO_WHITESPACE) -1 - if (present(offset)) indentDepth = indentDepth + offset + + indentDepth = verify(line,IO_WHITESPACE) - 1 + misc_optional(offset,0) end function indentDepth !-------------------------------------------------------------------------------------------------- -! @brief check whether a string is in flow style, i.e. starts with '{' or '[' +! @brief Check whether a string is in flow style, i.e. starts with '{' or '['. !-------------------------------------------------------------------------------------------------- logical function isFlow(line) character(len=*), intent(in) :: line + isFlow = index(adjustl(line),'[') == 1 .or. index(adjustl(line),'{') == 1 end function isFlow !-------------------------------------------------------------------------------------------------- -! @brief check whether a string is a scalar item, i.e. starts without any special symbols +! @brief Check whether a string is a scalar item, i.e. starts without any special symbols. !-------------------------------------------------------------------------------------------------- logical function isScalar(line) character(len=*), intent(in) :: line + isScalar = (.not. isKeyValue(line) .and. & .not. isKey(line) .and. & .not. isListItem(line) .and. & @@ -280,12 +284,13 @@ end function isScalar !-------------------------------------------------------------------------------------------------- -! @brief check whether a string is a list item, i.e. starts with '-' +! @brief Check whether a string is a list item, i.e. starts with '-'. !-------------------------------------------------------------------------------------------------- logical function isListItem(line) character(len=*), intent(in) :: line + isListItem = .false. if (len_trim(adjustl(line))> 2 .and. index(trim(adjustl(line)), '-') == 1) then isListItem = scan(trim(adjustl(line)),' ') == 2 @@ -297,13 +302,14 @@ end function isListItem !-------------------------------------------------------------------------------------------------- -! @brief check whether a string contains a key value pair of the for ': ' +! @brief Check whether a string contains a key-value pair of the form ': '. !-------------------------------------------------------------------------------------------------- logical function isKeyValue(line) character(len=*), intent(in) :: line isKeyValue = .false. + if ( .not. isKey(line) .and. index(IO_rmComment(line),':') > 0 .and. .not. isFlow(line)) then if (index(IO_rmComment(line),': ') > 0) isKeyValue = .true. end if @@ -312,13 +318,14 @@ end function isKeyValue !-------------------------------------------------------------------------------------------------- -! @brief check whether a string contains a key without a value, i.e. it ends with ':' -! ToDo: check whether this is safe for trailing spaces followed by a new line character +! @brief Check whether a string contains a key without a value, i.e. it ends in ':'. +! ToDo: check whether this is safe for trailing spaces followed by a newline character !-------------------------------------------------------------------------------------------------- logical function isKey(line) character(len=*), intent(in) :: line + if (len(IO_rmComment(line)) == 0) then isKey = .false. else @@ -331,20 +338,21 @@ end function isKey !-------------------------------------------------------------------------------------------------- -! @brief check whether a string is a list in flow style +! @brief Check whether a string is a list in flow style. !-------------------------------------------------------------------------------------------------- logical function isFlowList(line) character(len=*), intent(in) :: line + isFlowList = index(adjustl(line),'[') == 1 end function isFlowList !-------------------------------------------------------------------------------------------------- -! @brief skip empty lines -! @details update start position in the block by skipping empty lines if present. +! @brief Skip empty lines. +! @details Update start position in the block by skipping empty lines if present. !-------------------------------------------------------------------------------------------------- subroutine skip_empty_lines(blck,s_blck) @@ -353,6 +361,7 @@ subroutine skip_empty_lines(blck,s_blck) logical :: empty + empty = .true. do while(empty .and. len_trim(blck(s_blck:)) /= 0) empty = len_trim(IO_rmComment(blck(s_blck:s_blck + index(blck(s_blck:),IO_EOL) - 2))) == 0 @@ -363,8 +372,8 @@ end subroutine skip_empty_lines !-------------------------------------------------------------------------------------------------- -! @brief skip file header -! @details update start position in the block by skipping file header if present. +! @brief Skip file header. +! @details Update start position in the block by skipping file header if present. !-------------------------------------------------------------------------------------------------- subroutine skip_file_header(blck,s_blck) @@ -373,6 +382,7 @@ subroutine skip_file_header(blck,s_blck) character(len=:), allocatable :: line + line = IO_rmComment(blck(s_blck:s_blck + index(blck(s_blck:),IO_EOL) - 2)) if (index(adjustl(line),'%YAML') == 1) then s_blck = s_blck + index(blck(s_blck:),IO_EOL) @@ -388,7 +398,7 @@ end subroutine skip_file_header !-------------------------------------------------------------------------------------------------- -!> @brief check if a line in flow YAML starts and ends in the same line +!> @brief Check whether a line in flow style starts and ends on the same line. !-------------------------------------------------------------------------------------------------- logical function flow_is_closed(str,e_char) @@ -399,6 +409,7 @@ logical function flow_is_closed(str,e_char) i character(len=:), allocatable:: line + flow_is_closed = .false. N_sq = 0 N_cu = 0 @@ -417,7 +428,7 @@ end function flow_is_closed !-------------------------------------------------------------------------------------------------- -!> @brief return the flow YAML line without line break +!> @brief Return a flow-style line without line break. !-------------------------------------------------------------------------------------------------- subroutine remove_line_break(blck,s_blck,e_char,flow_line) @@ -427,6 +438,7 @@ subroutine remove_line_break(blck,s_blck,e_char,flow_line) character(len=:), allocatable, intent(out) :: flow_line logical :: line_end + line_end =.false. flow_line = '' @@ -440,7 +452,7 @@ end subroutine remove_line_break !-------------------------------------------------------------------------------------------------- -!> @brief return the scalar list item without line break +!> @brief Return a scalar list item without line break. !-------------------------------------------------------------------------------------------------- subroutine list_item_inline(blck,s_blck,inline,offset) @@ -452,6 +464,7 @@ subroutine list_item_inline(blck,s_blck,inline,offset) character(len=:), allocatable :: line integer :: indent,indent_next + indent = indentDepth(blck(s_blck:),offset) line = IO_rmComment(blck(s_blck:s_blck + index(blck(s_blck:),IO_EOL) - 2)) inline = line(indent-offset+3:) @@ -471,8 +484,8 @@ end subroutine list_item_inline !-------------------------------------------------------------------------------------------------- -! @brief reads a line of YAML block which is already in flow style -! @details Dicts should be enlcosed within '{}' for it to be consistent with DAMASK YAML parser +! @brief Read a line of YAML block that is already in flow style. +! @details A dict should be enclosed within '{}' for it to be consistent with the DAMASK YAML parser. !-------------------------------------------------------------------------------------------------- recursive subroutine line_isFlow(flow,s_flow,line) @@ -485,6 +498,7 @@ recursive subroutine line_isFlow(flow,s_flow,line) list_chunk, & dict_chunk + if (index(adjustl(line),'[') == 1) then s = index(line,'[') flow(s_flow:s_flow) = '[' @@ -535,8 +549,8 @@ end subroutine line_isFlow !------------------------------------------------------------------------------------------------- -! @brief reads a line of YAML block of type : and places it in the YAML flow style structure -! @details Makes sure that the is consistent with the input required in DAMASK YAML parser +! @brief Transform a line of YAML of type : to flow style. +! @details Ensures that the is consistent with the input required in the DAMASK YAML parser. !------------------------------------------------------------------------------------------------- recursive subroutine keyValue_toFlow(flow,s_flow,line) @@ -550,6 +564,7 @@ recursive subroutine keyValue_toFlow(flow,s_flow,line) col_pos, & offset_value + col_pos = index(line,':') if (line(col_pos+1:col_pos+1) /= ' ') call IO_error(704,ext_msg=line) if (isFlow(line(col_pos+1:))) then @@ -567,7 +582,7 @@ end subroutine keyValue_toFlow !------------------------------------------------------------------------------------------------- -! @brief reads a line of YAML block and places it in the YAML flow style structure +! @brief Transform a line of YAML to flow style. !------------------------------------------------------------------------------------------------- subroutine line_toFlow(flow,s_flow,line) @@ -586,11 +601,11 @@ end subroutine line_toFlow !------------------------------------------------------------------------------------------------- -! @brief convert a yaml list in block style to a yaml list in flow style +! @brief Transform a block-style list to flow style. ! @details enters the function when encountered with the list indicator '- ' ! reads each scalar list item and separates each other with a ',' ! If list item is non scalar, it stores the offset for that list item block -! Increase in the indentation level or when list item is not scalar -> 'decide' function is called. +! Call the 'decide' function if there is an increase in the indentation level or the list item is not a scalar ! decrease in indentation level indicates the end of an indentation block !------------------------------------------------------------------------------------------------- recursive subroutine lst(blck,flow,s_blck,s_flow,offset) @@ -679,7 +694,7 @@ end subroutine lst !-------------------------------------------------------------------------------------------------- -! @brief convert a yaml dict in block style to a yaml dict in flow style +! @brief Transform a block-style dict to flow style. ! @details enters the function when encountered with the dictionary indicator ':' ! parses each line in the block and compares indentation of a line with the preceding line ! upon increase in indentation level -> 'decide' function decides if the line is a list or dict @@ -817,7 +832,7 @@ end subroutine decide !-------------------------------------------------------------------------------------------------- -!> @brief Convert all block style YAML parts to flow style. +!> @brief Convert all block-style parts to flow style. !> @details The input needs to end with a newline. !-------------------------------------------------------------------------------------------------- function to_flow(blck) diff --git a/src/config.f90 b/src/config.f90 index 7ab9c76f8..e5f9011fb 100644 --- a/src/config.f90 +++ b/src/config.f90 @@ -1,12 +1,13 @@ !-------------------------------------------------------------------------------------------------- !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH -!> @brief Read in the configuration of material, numerics, and debug from their respective file +!> @brief Read in the material and numerics configuration from their respective file. !-------------------------------------------------------------------------------------------------- module config use IO + use misc use YAML_parse use YAML_types - use results + use result use parallelization implicit none(type,external) @@ -14,17 +15,18 @@ module config type(tDict), pointer, public :: & config_material, & - config_numerics, & - config_debug + config_numerics public :: & config_init, & - config_deallocate + config_material_deallocate, & + config_numerics_deallocate, & + config_listReferences contains !-------------------------------------------------------------------------------------------------- -!> @brief Real *.yaml configuration files. +!> @brief Read *.yaml configuration files. !-------------------------------------------------------------------------------------------------- subroutine config_init() @@ -32,11 +34,62 @@ subroutine config_init() call parse_material() call parse_numerics() - call parse_debug() end subroutine config_init +!-------------------------------------------------------------------------------------------------- +!> @brief Deallocate config_material. +!-------------------------------------------------------------------------------------------------- +subroutine config_material_deallocate() + + print'(/,1x,a)', 'deallocating material configuration'; flush(IO_STDOUT) + deallocate(config_material) + +end subroutine config_material_deallocate + +!-------------------------------------------------------------------------------------------------- +!> @brief Deallocate config_numerics if present. +!-------------------------------------------------------------------------------------------------- +subroutine config_numerics_deallocate() + + if (.not. associated(config_numerics, emptyDict)) then + print'(/,1x,a)', 'deallocating numerics configuration'; flush(IO_STDOUT) + deallocate(config_numerics) + end if + +end subroutine config_numerics_deallocate + + +!-------------------------------------------------------------------------------------------------- +!> @brief Return string with references from dict. +!-------------------------------------------------------------------------------------------------- +function config_listReferences(config,indent) result(references) + + type(tDict) :: config + integer, optional :: indent + character(len=:), allocatable :: references + + + type(tList), pointer :: ref + character(len=:), allocatable :: filler + integer :: r + + + filler = repeat(' ',misc_optional(indent,0)) + ref => config%get_list('references',emptyList) + if (ref%length == 0) then + references = '' + else + references = 'references:' + do r = 1, ref%length + references = references//IO_EOL//filler//'- '//IO_wrapLines(ref%get_asString(r),filler=filler//' ') + end do + end if + +end function config_listReferences + + !-------------------------------------------------------------------------------------------------- !> @brief Read material.yaml. !-------------------------------------------------------------------------------------------------- @@ -52,9 +105,9 @@ subroutine parse_material() if (worldrank == 0) then print'(/,1x,a)', 'reading material.yaml'; flush(IO_STDOUT) fileContent = IO_read('material.yaml') - call results_openJobFile(parallel=.false.) - call results_writeDataset_str(fileContent,'setup','material.yaml','main configuration') - call results_closeJobFile + call result_openJobFile(parallel=.false.) + call result_writeDataset_str(fileContent,'setup','material.yaml','main configuration') + call result_closeJobFile() end if call parallelization_bcast_str(fileContent) @@ -81,9 +134,9 @@ subroutine parse_numerics() print'(1x,a)', 'reading numerics.yaml'; flush(IO_STDOUT) fileContent = IO_read('numerics.yaml') if (len(fileContent) > 0) then - call results_openJobFile(parallel=.false.) - call results_writeDataset_str(fileContent,'setup','numerics.yaml','numerics configuration') - call results_closeJobFile + call result_openJobFile(parallel=.false.) + call result_writeDataset_str(fileContent,'setup','numerics.yaml','numerics configuration') + call result_closeJobFile() end if end if call parallelization_bcast_str(fileContent) @@ -94,47 +147,4 @@ subroutine parse_numerics() end subroutine parse_numerics - -!-------------------------------------------------------------------------------------------------- -!> @brief Read debug.yaml. -!-------------------------------------------------------------------------------------------------- -subroutine parse_debug() - - logical :: fileExists - character(len=:), allocatable :: fileContent - - - config_debug => emptyDict - - inquire(file='debug.yaml', exist=fileExists) - if (fileExists) then - - if (worldrank == 0) then - print'(1x,a)', 'reading debug.yaml'; flush(IO_STDOUT) - fileContent = IO_read('debug.yaml') - if (len(fileContent) > 0) then - call results_openJobFile(parallel=.false.) - call results_writeDataset_str(fileContent,'setup','debug.yaml','debug configuration') - call results_closeJobFile - end if - end if - call parallelization_bcast_str(fileContent) - - config_debug => YAML_parse_str_asDict(fileContent) - - end if - -end subroutine parse_debug - - -!-------------------------------------------------------------------------------------------------- -!> @brief Deallocate config_material. -!ToDo: deallocation of numerics and debug (optional) -!-------------------------------------------------------------------------------------------------- -subroutine config_deallocate - - deallocate(config_material) - -end subroutine config_deallocate - end module config diff --git a/src/discretization.f90 b/src/discretization.f90 index 2c605b422..ad08c5bff 100644 --- a/src/discretization.f90 +++ b/src/discretization.f90 @@ -5,7 +5,7 @@ module discretization use prec - use results + use result implicit none(type,external) private @@ -29,7 +29,7 @@ module discretization public :: & discretization_init, & - discretization_results, & + discretization_result, & discretization_setIPcoords, & discretization_setNodeCoords @@ -76,21 +76,21 @@ end subroutine discretization_init !-------------------------------------------------------------------------------------------------- !> @brief write the displacements !-------------------------------------------------------------------------------------------------- -subroutine discretization_results +subroutine discretization_result() real(pReal), dimension(:,:), allocatable :: u - call results_closeGroup(results_addGroup('current/geometry')) + call result_closeGroup(result_addGroup('current/geometry')) u = discretization_NodeCoords (:,:discretization_sharedNodesBegin) & - discretization_NodeCoords0(:,:discretization_sharedNodesBegin) - call results_writeDataset(u,'current/geometry','u_n','displacements of the nodes','m') + call result_writeDataset(u,'current/geometry','u_n','displacements of the nodes','m') u = discretization_IPcoords & - discretization_IPcoords0 - call results_writeDataset(u,'current/geometry','u_p','displacements of the materialpoints (cell centers)','m') + call result_writeDataset(u,'current/geometry','u_p','displacements of the materialpoints (cell centers)','m') -end subroutine discretization_results +end subroutine discretization_result !-------------------------------------------------------------------------------------------------- diff --git a/src/geometry_plastic_nonlocal.f90 b/src/geometry_plastic_nonlocal.f90 index f0da5539b..e9e7a19cc 100644 --- a/src/geometry_plastic_nonlocal.f90 +++ b/src/geometry_plastic_nonlocal.f90 @@ -7,7 +7,7 @@ !-------------------------------------------------------------------------------------------------- module geometry_plastic_nonlocal use prec - use results + use result implicit none(type,external) public @@ -110,39 +110,38 @@ end subroutine geometry_plastic_nonlocal_disable !--------------------------------------------------------------------------------------------------- !> @brief Write geometry data to results file !--------------------------------------------------------------------------------------------------- -subroutine geometry_plastic_nonlocal_results +subroutine geometry_plastic_nonlocal_result() integer, dimension(:), allocatable :: shp - call results_openJobFile + call result_openJobFile() writeVolume: block real(pReal), dimension(:), allocatable :: temp shp = shape(geometry_plastic_nonlocal_IPvolume0) temp = reshape(geometry_plastic_nonlocal_IPvolume0,[shp(1)*shp(2)]) - call results_writeDataset(temp,'geometry','v_0',& - 'initial cell volume','m³') + call result_writeDataset(temp,'geometry','v_0',& + 'initial cell volume','m³') end block writeVolume writeAreas: block real(pReal), dimension(:,:), allocatable :: temp shp = shape(geometry_plastic_nonlocal_IParea0) temp = reshape(geometry_plastic_nonlocal_IParea0,[shp(1),shp(2)*shp(3)]) - call results_writeDataset(temp,'geometry','a_0',& - 'initial cell face area','m²') + call result_writeDataset(temp,'geometry','a_0',& + 'initial cell face area','m²') end block writeAreas writeNormals: block real(pReal), dimension(:,:,:), allocatable :: temp shp = shape(geometry_plastic_nonlocal_IPareaNormal0) temp = reshape(geometry_plastic_nonlocal_IPareaNormal0,[shp(1),shp(2),shp(3)*shp(4)]) - call results_writeDataset(temp,'geometry','n_0',& - 'initial cell face normals','-',transposed=.false.) + call result_writeDataset(temp,'geometry','n_0',& + 'initial cell face normals','-',transposed=.false.) end block writeNormals + call result_closeJobFile() - call results_closeJobFile - -end subroutine geometry_plastic_nonlocal_results +end subroutine geometry_plastic_nonlocal_result end module geometry_plastic_nonlocal diff --git a/src/grid/DAMASK_grid.f90 b/src/grid/DAMASK_grid.f90 index 2e21dec8d..c77832346 100644 --- a/src/grid/DAMASK_grid.f90 +++ b/src/grid/DAMASK_grid.f90 @@ -15,7 +15,7 @@ program DAMASK_grid use prec use parallelization - use signals + use signal use CLI use IO use config @@ -28,7 +28,7 @@ program DAMASK_grid use grid_mechanical_FEM use grid_damage_spectral use grid_thermal_spectral - use results + use result #if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY) implicit none(type,external) @@ -37,7 +37,7 @@ program DAMASK_grid #endif type :: tLoadCase - type(tRotation) :: rot !< rotation of BC + type(tRotation) :: rot !< rotation of BC type(tBoundaryCondition) :: stress, & !< stress BC deformation !< deformation BC (dot_F, F, or L) real(pReal) :: t, & !< length of increment @@ -73,7 +73,7 @@ program DAMASK_grid guess, & !< guess along former trajectory stagIterate, & cutBack = .false.,& - signal + sig integer :: & i, j, m, field, & errorID = 0, & @@ -133,7 +133,7 @@ program DAMASK_grid !------------------------------------------------------------------------------------------------- -! reading field paramters from numerics file and do sanity checks +! read (and check) field parameters from numerics file num_grid => config_numerics%get_dict('grid', defaultVal=emptyDict) stagItMax = num_grid%get_asInt('maxStaggeredIter',defaultVal=10) maxCutBack = num_grid%get_asInt('maxCutBack',defaultVal=3) @@ -145,9 +145,9 @@ program DAMASK_grid fileContent = IO_read(CLI_loadFile) fname = CLI_loadFile if (scan(fname,'/') /= 0) fname = fname(scan(fname,'/',.true.)+1:) - call results_openJobFile(parallel=.false.) - call results_writeDataset_str(fileContent,'setup',fname,'load case definition (grid solver)') - call results_closeJobFile + call result_openJobFile(parallel=.false.) + call result_writeDataset_str(fileContent,'setup',fname,'load case definition (grid solver)') + call result_closeJobFile() end if call parallelization_bcast_str(fileContent) @@ -313,7 +313,8 @@ program DAMASK_grid !-------------------------------------------------------------------------------------------------- ! doing initialization depending on active solvers - call spectral_Utilities_init + call spectral_Utilities_init() + do field = 2, nActiveFields select case (ID(field)) @@ -327,6 +328,7 @@ program DAMASK_grid end do call mechanical_init() + call config_numerics_deallocate() !-------------------------------------------------------------------------------------------------- ! write header of output file @@ -343,7 +345,7 @@ program DAMASK_grid writeUndeformed: if (CLI_restartInc < 1) then print'(/,1x,a)', '... writing initial configuration to file .................................' flush(IO_STDOUT) - call materialpoint_results(0,0.0_pReal) + call materialpoint_result(0,0.0_pReal) end if writeUndeformed loadCaseLooping: do l = 1, size(loadCases) @@ -376,7 +378,7 @@ program DAMASK_grid stepFraction = stepFraction + 1 ! count step !-------------------------------------------------------------------------------------------------- -! report begin of new step +! report beginning of new step print'(/,1x,a)', '###########################################################################' print'(1x,a,1x,es12.5,6(a,i0))', & 'Time', t, & @@ -430,11 +432,11 @@ program DAMASK_grid end do !-------------------------------------------------------------------------------------------------- -! check solution for either advance or retry +! check solution and either advance or retry with smaller timestep if ( (all(solres(:)%converged .and. solres(:)%stagConverged)) & ! converged .and. .not. solres(1)%termIll) then ! and acceptable solution found - call mechanical_updateCoords + call mechanical_updateCoords() Delta_t_prev = Delta_t cutBack = .false. guess = .true. ! start guessing after first converged (sub)inc @@ -465,33 +467,33 @@ program DAMASK_grid print'(/,1x,a,i0,a)', 'increment ', totalIncsCounter, ' NOT converged' end if; flush(IO_STDOUT) - call MPI_Allreduce(signals_SIGUSR1,signal,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI) + call MPI_Allreduce(signal_SIGUSR1,sig,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' - if (mod(inc,loadCases(l)%f_out) == 0 .or. signal) then + if (mod(inc,loadCases(l)%f_out) == 0 .or. sig) then print'(/,1x,a)', '... writing results to file ...............................................' flush(IO_STDOUT) - call materialpoint_results(totalIncsCounter,t) + call materialpoint_result(totalIncsCounter,t) end if - if (signal) call signals_setSIGUSR1(.false.) - call MPI_Allreduce(signals_SIGUSR2,signal,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI) + if (sig) call signal_setSIGUSR1(.false.) + call MPI_Allreduce(signal_SIGUSR2,sig,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' - if (mod(inc,loadCases(l)%f_restart) == 0 .or. signal) then + if (mod(inc,loadCases(l)%f_restart) == 0 .or. sig) then do field = 1, nActiveFields select case (ID(field)) case(FIELD_MECH_ID) - call mechanical_restartWrite + call mechanical_restartWrite() case(FIELD_THERMAL_ID) - call grid_thermal_spectral_restartWrite + call grid_thermal_spectral_restartWrite() case(FIELD_DAMAGE_ID) - call grid_damage_spectral_restartWrite + call grid_damage_spectral_restartWrite() end select end do - call materialpoint_restartWrite + call materialpoint_restartWrite() end if - if (signal) call signals_setSIGUSR2(.false.) - call MPI_Allreduce(signals_SIGINT,signal,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI) + if (sig) call signal_setSIGUSR2(.false.) + call MPI_Allreduce(signal_SIGINT,sig,1_MPI_INTEGER_KIND,MPI_LOGICAL,MPI_LOR,MPI_COMM_WORLD,err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' - if (signal) exit loadCaseLooping + if (sig) exit loadCaseLooping end if skipping end do incLooping diff --git a/src/grid/base64.f90 b/src/grid/base64.f90 index 40986d783..ee38e0b19 100644 --- a/src/grid/base64.f90 +++ b/src/grid/base64.f90 @@ -29,7 +29,7 @@ subroutine base64_init print'(/,1x,a)', '<<<+- base64 init -+>>>'; flush(IO_STDOUT) - call selfTest + call selfTest() end subroutine base64_init diff --git a/src/grid/discretization_grid.f90 b/src/grid/discretization_grid.f90 index 999b8f460..ee44f5907 100644 --- a/src/grid/discretization_grid.f90 +++ b/src/grid/discretization_grid.f90 @@ -19,7 +19,7 @@ module discretization_grid use CLI use IO use config - use results + use result use discretization use geometry_plastic_nonlocal @@ -65,8 +65,7 @@ subroutine discretization_grid_init(restart) materialAt, materialAt_global integer :: & - j, & - debug_element, debug_ip + j integer(MPI_INTEGER_KIND) :: err_MPI integer(C_INTPTR_T) :: & devNull, z, z_offset @@ -89,9 +88,9 @@ subroutine discretization_grid_init(restart) call IO_error(180,ext_msg='mismatch in # of material IDs and cells') fname = CLI_geomFile if (scan(fname,'/') /= 0) fname = fname(scan(fname,'/',.true.)+1:) - call results_openJobFile(parallel=.false.) - call results_writeDataset_str(fileContent,'setup',fname,'geometry definition (grid solver)') - call results_closeJobFile + call result_openJobFile(parallel=.false.) + call result_writeDataset_str(fileContent,'setup',fname,'geometry definition (grid solver)') + call result_closeJobFile() else allocate(materialAt_global(0)) ! needed for IntelMPI end if @@ -147,12 +146,12 @@ subroutine discretization_grid_init(restart) !-------------------------------------------------------------------------------------------------- ! store geometry information for post processing if (.not. restart) then - call results_openJobFile - call results_closeGroup(results_addGroup('geometry')) - call results_addAttribute('cells', cells, '/geometry') - call results_addAttribute('size', geomSize,'/geometry') - call results_addAttribute('origin',origin, '/geometry') - call results_closeJobFile + call result_openJobFile() + call result_closeGroup(result_addGroup('geometry')) + call result_addAttribute('cells', cells, '/geometry') + call result_addAttribute('size', geomSize,'/geometry') + call result_addAttribute('origin',origin, '/geometry') + call result_closeJobFile() end if !-------------------------------------------------------------------------------------------------- @@ -163,13 +162,6 @@ subroutine discretization_grid_init(restart) call geometry_plastic_nonlocal_setIPareaNormal (cellSurfaceNormal(product(myGrid))) call geometry_plastic_nonlocal_setIPneighborhood(IPneighborhood(myGrid)) -!------------------------------------------------------------------------------------------------- -! debug parameters - debug_element = config_debug%get_asInt('element',defaultVal=1) - if (debug_element < 1 .or. debug_element > product(myGrid)) call IO_error(602,ext_msg='element') - debug_ip = config_debug%get_asInt('integrationpoint',defaultVal=1) - if (debug_ip /= 1) call IO_error(602,ext_msg='IP') - end subroutine discretization_grid_init diff --git a/src/grid/grid_damage_spectral.f90 b/src/grid/grid_damage_spectral.f90 index e096ec3ef..0ba3c5a31 100644 --- a/src/grid/grid_damage_spectral.f90 +++ b/src/grid/grid_damage_spectral.f90 @@ -298,7 +298,7 @@ subroutine grid_damage_spectral_forward(cutBack) end do; end do; end do else phi_lastInc = phi - call updateReference + call updateReference() end if end subroutine grid_damage_spectral_forward diff --git a/src/grid/grid_mech_FEM.f90 b/src/grid/grid_mech_FEM.f90 index e247deaad..d55f58152 100644 --- a/src/grid/grid_mech_FEM.f90 +++ b/src/grid/grid_mech_FEM.f90 @@ -50,8 +50,6 @@ module grid_mechanical_FEM type(tNumerics) :: num ! numerics parameters. Better name? - logical :: debugRotation - !-------------------------------------------------------------------------------------------------- ! PETSc data DM :: mechanical_grid @@ -121,19 +119,12 @@ subroutine grid_mechanical_FEM_init integer(HID_T) :: fileHandle, groupHandle type(tDict), pointer :: & num_grid - type(tList), pointer :: & - debug_grid character(len=pStringLen) :: & extmsg = '' print'(/,1x,a)', '<<<+- grid_mechanical_FEM init -+>>>'; flush(IO_STDOUT) -!------------------------------------------------------------------------------------------------- -! debugging options - debug_grid => config_debug%get_list('grid',defaultVal=emptyList) - debugRotation = debug_grid%contains('rotation') - !------------------------------------------------------------------------------------------------- ! read numerical parameters and do sanity checks num_grid => config_numerics%get_dict('grid',defaultVal=emptyDict) @@ -565,7 +556,8 @@ subroutine formResidual(da_local,x_local, & newIteration: if (totalIter <= PETScIter) then totalIter = totalIter + 1 print'(1x,a,3(a,i0))', trim(incInfo), ' @ Iteration ', num%itmin, '≤',totalIter+1, '≤', num%itmax - if (debugRotation) print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & + if (any(dNeq(params%rotation_BC%asQuaternion(), real([1.0, 0.0, 0.0, 0.0],pReal)))) & + print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & 'deformation gradient aim (lab) =', transpose(params%rotation_BC%rotate(F_aim,active=.true.)) print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & 'deformation gradient aim =', transpose(F_aim) @@ -602,13 +594,12 @@ subroutine formResidual(da_local,x_local, & !-------------------------------------------------------------------------------------------------- ! constructing residual - call VecSet(f_local,0.0_pReal,err_PETSc) - CHKERRQ(err_PETSc) call DMDAVecGetArrayF90(da_local,f_local,r,err_PETSc) CHKERRQ(err_PETSc) call DMDAVecGetArrayF90(da_local,x_local,x_scal,err_PETSc) CHKERRQ(err_PETSc) ele = 0 + r = 0.0_pReal do k = cells3Offset+1, cells3Offset+cells3; do j = 1, cells(2); do i = 1, cells(1) ctr = 0 do kk = -1, 0; do jj = -1, 0; do ii = -1, 0 @@ -628,13 +619,9 @@ subroutine formResidual(da_local,x_local, & end do; end do; end do call DMDAVecRestoreArrayF90(da_local,x_local,x_scal,err_PETSc) CHKERRQ(err_PETSc) - call DMDAVecRestoreArrayF90(da_local,f_local,r,err_PETSc) - CHKERRQ(err_PETSc) !-------------------------------------------------------------------------------------------------- ! applying boundary conditions - call DMDAVecGetArrayF90(da_local,f_local,r,err_PETSc) - CHKERRQ(err_PETSc) if (cells3Offset == 0) then r(0:2,0, 0, 0) = 0.0_pReal r(0:2,cells(1),0, 0) = 0.0_pReal diff --git a/src/grid/grid_mech_spectral_basic.f90 b/src/grid/grid_mech_spectral_basic.f90 index 6f5a85815..f2a009afb 100644 --- a/src/grid/grid_mech_spectral_basic.f90 +++ b/src/grid/grid_mech_spectral_basic.f90 @@ -49,8 +49,6 @@ module grid_mechanical_spectral_basic type(tNumerics) :: num ! numerics parameters. Better name? - logical :: debugRotation - !-------------------------------------------------------------------------------------------------- ! PETSc data DM :: da @@ -115,15 +113,8 @@ subroutine grid_mechanical_spectral_basic_init() PetscInt, dimension(0:worldsize-1) :: localK real(pReal), dimension(3,3,product(cells(1:2))*cells3) :: temp33n integer(HID_T) :: fileHandle, groupHandle -#if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY) - type(MPI_File) :: fileUnit -#else - integer :: fileUnit -#endif type(tDict), pointer :: & num_grid - type(tList), pointer :: & - debug_grid character(len=pStringLen) :: & extmsg = '' @@ -136,11 +127,6 @@ subroutine grid_mechanical_spectral_basic_init() print'( 1x,a)', 'P. Shanthraj et al., International Journal of Plasticity 66:31–45, 2015' print'( 1x,a)', 'https://doi.org/10.1016/j.ijplas.2014.02.006' -!------------------------------------------------------------------------------------------------- -! debugging options - debug_grid => config_debug%get_list('grid',defaultVal=emptyList) - debugRotation = debug_grid%contains('rotation') - !------------------------------------------------------------------------------------------------- ! read numerical parameters and do sanity checks num_grid => config_numerics%get_dict('grid',defaultVal=emptyDict) @@ -523,7 +509,8 @@ subroutine formResidual(residual_subdomain, F, & newIteration: if (totalIter <= PETScIter) then totalIter = totalIter + 1 print'(1x,a,3(a,i0))', trim(incInfo), ' @ Iteration ', num%itmin, '≤',totalIter, '≤', num%itmax - if (debugRotation) print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & + if (any(dNeq(params%rotation_BC%asQuaternion(), real([1.0, 0.0, 0.0, 0.0],pReal)))) & + print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & 'deformation gradient aim (lab) =', transpose(params%rotation_BC%rotate(F_aim,active=.true.)) print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & 'deformation gradient aim =', transpose(F_aim) diff --git a/src/grid/grid_mech_spectral_polarisation.f90 b/src/grid/grid_mech_spectral_polarisation.f90 index 52b20dfbd..7bdd84d25 100644 --- a/src/grid/grid_mech_spectral_polarisation.f90 +++ b/src/grid/grid_mech_spectral_polarisation.f90 @@ -54,8 +54,6 @@ module grid_mechanical_spectral_polarisation type(tNumerics) :: num ! numerics parameters. Better name? - logical :: debugRotation - !-------------------------------------------------------------------------------------------------- ! PETSc data DM :: da @@ -128,27 +126,17 @@ subroutine grid_mechanical_spectral_polarisation_init() PetscInt, dimension(0:worldsize-1) :: localK real(pReal), dimension(3,3,product(cells(1:2))*cells3) :: temp33n integer(HID_T) :: fileHandle, groupHandle -#if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY) - type(MPI_File) :: fileUnit -#else - integer :: fileUnit -#endif type(tDict), pointer :: & num_grid - type(tList), pointer :: & - debug_grid character(len=pStringLen) :: & extmsg = '' + print'(/,1x,a)', '<<<+- grid_mechanical_spectral_polarization init -+>>>'; flush(IO_STDOUT) print'(/,1x,a)', 'P. Shanthraj et al., International Journal of Plasticity 66:31–45, 2015' print'( 1x,a)', 'https://doi.org/10.1016/j.ijplas.2014.02.006' -!------------------------------------------------------------------------------------------------- -! debugging options - debug_grid => config_debug%get_list('grid',defaultVal=emptyList) - debugRotation = debug_grid%contains('rotation') !------------------------------------------------------------------------------------------------- ! read numerical parameters and do sanity checks @@ -599,7 +587,8 @@ subroutine formResidual(residual_subdomain, FandF_tau, & newIteration: if (totalIter <= PETScIter) then totalIter = totalIter + 1 print'(1x,a,3(a,i0))', trim(incInfo), ' @ Iteration ', num%itmin, '≤',totalIter, '≤', num%itmax - if (debugRotation) print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & + if (any(dNeq(params%rotation_BC%asQuaternion(), real([1.0, 0.0, 0.0, 0.0],pReal)))) & + print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & 'deformation gradient aim (lab) =', transpose(params%rotation_BC%rotate(F_aim,active=.true.)) print'(/,1x,a,/,2(3(f12.7,1x)/),3(f12.7,1x))', & 'deformation gradient aim =', transpose(F_aim) diff --git a/src/grid/grid_thermal_spectral.f90 b/src/grid/grid_thermal_spectral.f90 index a5d9f4ec8..6483c91c6 100644 --- a/src/grid/grid_thermal_spectral.f90 +++ b/src/grid/grid_thermal_spectral.f90 @@ -276,7 +276,7 @@ subroutine grid_thermal_spectral_forward(cutBack) else dotT_lastInc = (T - T_lastInc)/params%Delta_t T_lastInc = T - call updateReference + call updateReference() end if end subroutine grid_thermal_spectral_forward diff --git a/src/grid/spectral_utilities.f90 b/src/grid/spectral_utilities.f90 index 8fe62012b..5821bd3c0 100644 --- a/src/grid/spectral_utilities.f90 +++ b/src/grid/spectral_utilities.f90 @@ -64,13 +64,6 @@ module spectral_utilities planScalarForth, & !< FFTW MPI plan s(x) to s(k) planScalarBack !< FFTW MPI plan s(k) to s(x) -!-------------------------------------------------------------------------------------------------- -! variables controlling debugging - logical :: & - debugGeneral, & !< general debugging of spectral solver - debugRotation, & !< also printing out results in lab frame - debugPETSc !< use some in debug defined options for more verbose PETSc solution - !-------------------------------------------------------------------------------------------------- ! derived types type, public :: tSolutionState !< return type of solution from spectral solver variants @@ -131,12 +124,7 @@ module spectral_utilities contains !-------------------------------------------------------------------------------------------------- -!> @brief allocates all neccessary fields, sets debug flags, create plans for FFTW -!> @details Sets the debug levels for general, divergence, restart, and FFTW from the bitwise coding -!> provided by the debug module to logicals. -!> Allocate all fields used by FFTW and create the corresponding plans depending on the debug -!> level chosen. -!> Initializes FFTW. +!> @brief Allocate all neccessary fields and create plans for FFTW. !-------------------------------------------------------------------------------------------------- subroutine spectral_utilities_init() @@ -157,12 +145,8 @@ subroutine spectral_utilities_init() integer(C_INTPTR_T), parameter :: & vectorSize = 3_C_INTPTR_T, & tensorSize = 9_C_INTPTR_T - character(len=*), parameter :: & - PETSCDEBUG = ' -snes_view -snes_monitor ' type(tDict) , pointer :: & num_grid - type(tList) , pointer :: & - debug_grid print'(/,1x,a)', '<<<+- spectral_utilities init -+>>>' @@ -179,25 +163,10 @@ subroutine spectral_utilities_init() print'( 1x,a)', 'P. Shanthraj et al., Handbook of Mechanics of Materials, 2019' print'( 1x,a)', 'https://doi.org/10.1007/978-981-10-6855-3_80' -!-------------------------------------------------------------------------------------------------- -! set debugging parameters - num_grid => config_numerics%get_dict('grid',defaultVal=emptyDict) - - debug_grid => config_debug%get_List('grid',defaultVal=emptyList) - debugGeneral = debug_grid%contains('basic') - debugRotation = debug_grid%contains('rotation') - debugPETSc = debug_grid%contains('PETSc') - - if (debugPETSc) print'(3(/,1x,a),/)', & - 'Initializing PETSc with debug options: ', & - trim(PETScDebug), & - 'add more using the "PETSc_options" keyword in numerics.yaml' - flush(IO_STDOUT) + num_grid => config_numerics%get_dict('grid',defaultVal=emptyDict) call PetscOptionsClear(PETSC_NULL_OPTIONS,err_PETSc) CHKERRQ(err_PETSc) - if (debugPETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(PETSCDEBUG),err_PETSc) - CHKERRQ(err_PETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,& num_grid%get_asString('PETSc_options',defaultVal=''),err_PETSc) CHKERRQ(err_PETSc) @@ -370,8 +339,8 @@ end subroutine spectral_utilities_init !--------------------------------------------------------------------------------------------------- -!> @brief updates reference stiffness and potentially precalculated gamma operator -!> @details Sets the current reference stiffness to the stiffness given as an argument. +!> @brief Update reference stiffness and potentially precalculated gamma operator. +!> @details Set 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. !--------------------------------------------------------------------------------------------------- @@ -430,19 +399,8 @@ end subroutine utilities_updateGamma !-------------------------------------------------------------------------------------------------- -!> @brief backward FFT of data in field_fourier to field_real -!> @details Does an weighted inverse FFT transform from complex to real -!-------------------------------------------------------------------------------------------------- -subroutine utilities_FFTvectorBackward() - - call fftw_mpi_execute_dft_c2r(planVectorBack,vectorField_fourier,vectorField_real) - vectorField_real = vectorField_real * wgt ! normalize the result by number of elements - -end subroutine utilities_FFTvectorBackward - - -!-------------------------------------------------------------------------------------------------- -!> @brief doing convolution gamma_hat * field_real, ensuring that average value = fieldAim +!> @brief Calculate gamma_hat * field_real (convolution). +!> @details The average value equals the given aim. !-------------------------------------------------------------------------------------------------- function utilities_GammaConvolution(field, fieldAim) result(gammaField) @@ -704,13 +662,6 @@ function utilities_maskedCompliance(rot_BC,mask_stress,C) if (size_reduced > 0) then temp99_real = math_3333to99(rot_BC%rotate(C)) - if (debugGeneral) then - print'(/,1x,a)', '... updating masked compliance ............................................' - print'(/,1x,a,/,8(9(2x,f12.7,1x)/),9(2x,f12.7,1x))', & - 'Stiffness C (load) / GPa =', transpose(temp99_Real)*1.0e-9_pReal - flush(IO_STDOUT) - end if - do i = 1,9; do j = 1,9 mask(i,j) = mask_stressVector(i) .and. mask_stressVector(j) end do; end do @@ -724,7 +675,7 @@ function utilities_maskedCompliance(rot_BC,mask_stress,C) ! check if inversion was successful sTimesC = matmul(c_reduced,s_reduced) errmatinv = errmatinv .or. any(dNeq(sTimesC,math_eye(size_reduced),1.0e-12_pReal)) - if (debugGeneral .or. errmatinv) then + if (errmatinv) then write(formatString, '(i2)') size_reduced formatString = '(/,1x,a,/,'//trim(formatString)//'('//trim(formatString)//'(2x,es9.2,1x)/))' print trim(formatString), 'C * S (load) ', transpose(matmul(c_reduced,s_reduced)) @@ -738,12 +689,6 @@ function utilities_maskedCompliance(rot_BC,mask_stress,C) utilities_maskedCompliance = math_99to3333(temp99_Real) - if (debugGeneral) then - print'(/,1x,a,/,9(9(2x,f10.5,1x)/),9(2x,f10.5,1x))', & - 'Masked Compliance (load) * GPa =', transpose(temp99_Real)*1.0e9_pReal - flush(IO_STDOUT) - end if - end function utilities_maskedCompliance @@ -825,9 +770,12 @@ subroutine utilities_constitutiveResponse(P,P_av,C_volAvg,C_minmaxAvg,& P_av = sum(sum(sum(P,dim=5),dim=4),dim=3) * wgt call MPI_Allreduce(MPI_IN_PLACE,P_av,9_MPI_INTEGER_KIND,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD,err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' - if (debugRotation) print'(/,1x,a,/,2(3(2x,f12.4,1x)/),3(2x,f12.4,1x))', & - 'Piola--Kirchhoff stress (lab) / MPa =', transpose(P_av)*1.e-6_pReal - if (present(rotation_BC)) P_av = rotation_BC%rotate(P_av) + if (present(rotation_BC)) then + if (any(dNeq(rotation_BC%asQuaternion(), real([1.0, 0.0, 0.0, 0.0],pReal)))) & + print'(/,1x,a,/,2(3(2x,f12.4,1x)/),3(2x,f12.4,1x))', & + 'Piola--Kirchhoff stress (lab) / MPa =', transpose(P_av)*1.e-6_pReal + P_av = rotation_BC%rotate(P_av) + end if print'(/,1x,a,/,2(3(2x,f12.4,1x)/),3(2x,f12.4,1x))', & 'Piola--Kirchhoff stress / MPa =', transpose(P_av)*1.e-6_pReal flush(IO_STDOUT) @@ -871,7 +819,7 @@ end subroutine utilities_constitutiveResponse !-------------------------------------------------------------------------------------------------- -!> @brief calculates forward rate, either guessing or just add delta/Delta_t +!> @brief Calculate forward rate, either as local guess or as homogeneous add on. !-------------------------------------------------------------------------------------------------- pure function utilities_calculateRate(heterogeneous,field0,field,dt,avRate) @@ -986,9 +934,9 @@ subroutine utilities_updateCoords(F) real(pReal), dimension(3,3,cells(1),cells(2),cells3), intent(in) :: F - real(pReal), dimension(3, cells(1),cells(2),cells3) :: IPcoords - real(pReal), dimension(3, cells(1),cells(2),cells3+2) :: IPfluct_padded ! Fluctuations of cell center displacement (padded along z for MPI) - real(pReal), dimension(3, cells(1)+1,cells(2)+1,cells3+1) :: nodeCoords + real(pReal), dimension(3, cells(1),cells(2),cells3) :: x_p !< Point/cell center coordinates + real(pReal), dimension(3, cells(1),cells(2),0:cells3+1) :: u_tilde_p_padded !< Fluctuation of cell center displacement (padded along z for MPI) + real(pReal), dimension(3, cells(1)+1,cells(2)+1,cells3+1) :: x_n !< Node coordinates integer :: & i,j,k,n, & c @@ -1030,7 +978,7 @@ subroutine utilities_updateCoords(F) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' !-------------------------------------------------------------------------------------------------- - ! integration in Fourier space to get fluctuations of cell center discplacements + ! integration in Fourier space to get fluctuations of cell center displacements !$OMP PARALLEL DO do j = 1, cells2; do k = 1, cells(3); do i = 1, cells1Red if (any([i,j+cells2Offset,k] /= 1)) then @@ -1043,25 +991,24 @@ subroutine utilities_updateCoords(F) !$OMP END PARALLEL DO call fftw_mpi_execute_dft_c2r(planVectorBack,vectorField_fourier,vectorField_real) - vectorField_real = vectorField_real * wgt ! normalize the result by number of elements + u_tilde_p_padded(1:3,1:cells(1),1:cells(2),1:cells3) = vectorField_real(1:3,1:cells(1),1:cells(2),1:cells3) * wgt !-------------------------------------------------------------------------------------------------- ! pad cell center fluctuations along z-direction (needed when running MPI simulation) - IPfluct_padded(1:3,1:cells(1),1:cells(2),2:cells3+1) = vectorField_real(1:3,1:cells(1),1:cells(2),1:cells3) - c = product(shape(IPfluct_padded(:,:,:,1))) !< amount of data to transfer + c = product(shape(u_tilde_p_padded(:,:,:,1))) !< amount of data to transfer rank_t = modulo(worldrank+1_MPI_INTEGER_KIND,worldsize) rank_b = modulo(worldrank-1_MPI_INTEGER_KIND,worldsize) ! send bottom layer to process below - call MPI_Isend(IPfluct_padded(:,:,:,2), c,MPI_DOUBLE,rank_b,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(1),err_MPI) + call MPI_Isend(u_tilde_p_padded(:,:,:,1), c,MPI_DOUBLE,rank_b,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(1),err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' - call MPI_Irecv(IPfluct_padded(:,:,:,cells3+2),c,MPI_DOUBLE,rank_t,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(2),err_MPI) + call MPI_Irecv(u_tilde_p_padded(:,:,:,cells3+1),c,MPI_DOUBLE,rank_t,0_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(2),err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' ! send top layer to process above - call MPI_Isend(IPfluct_padded(:,:,:,cells3+1),c,MPI_DOUBLE,rank_t,1_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(3),err_MPI) + call MPI_Isend(u_tilde_p_padded(:,:,:,cells3) ,c,MPI_DOUBLE,rank_t,1_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(3),err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' - call MPI_Irecv(IPfluct_padded(:,:,:,1), c,MPI_DOUBLE,rank_b,1_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(4),err_MPI) + call MPI_Irecv(u_tilde_p_padded(:,:,:,0), c,MPI_DOUBLE,rank_b,1_MPI_INTEGER_KIND,MPI_COMM_WORLD,request(4),err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' call MPI_Waitall(4,request,status,err_MPI) @@ -1073,26 +1020,26 @@ subroutine utilities_updateCoords(F) #endif !-------------------------------------------------------------------------------------------------- - ! calculate nodal displacements - nodeCoords = 0.0_pReal + ! calculate nodal positions + x_n = 0.0_pReal do j = 0,cells(2); do k = 0,cells3; do i = 0,cells(1) - nodeCoords(1:3,i+1,j+1,k+1) = matmul(Favg,step*(real([i,j,k+cells3Offset],pReal))) + x_n(1:3,i+1,j+1,k+1) = matmul(Favg,step*(real([i,j,k+cells3Offset],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,cells(1))+1,modulo(me(2)-1,cells(2))+1,me(3)+1)*0.125_pReal + x_n(1:3,i+1,j+1,k+1) = x_n(1:3,i+1,j+1,k+1) & + + u_tilde_p_padded(1:3,modulo(me(1)-1,cells(1))+1,modulo(me(2)-1,cells(2))+1,me(3))*0.125_pReal end do averageFluct end do; end do; end do !-------------------------------------------------------------------------------------------------- - ! calculate cell center displacements + ! calculate cell center/point positions do k = 1,cells3; do j = 1,cells(2); do i = 1,cells(1) - IPcoords(1:3,i,j,k) = vectorField_real(1:3,i,j,k) & - + matmul(Favg,step*(real([i,j,k+cells3Offset],pReal)-0.5_pReal)) + x_p(1:3,i,j,k) = u_tilde_p_padded(1:3,i,j,k) & + + matmul(Favg,step*(real([i,j,k+cells3Offset],pReal)-0.5_pReal)) end do; end do; end do - call discretization_setNodeCoords(reshape(NodeCoords,[3,(cells(1)+1)*(cells(2)+1)*(cells3+1)])) - call discretization_setIPcoords (reshape(IPcoords, [3,cells(1)*cells(2)*cells3])) + call discretization_setNodeCoords(reshape(x_n,[3,(cells(1)+1)*(cells(2)+1)*(cells3+1)])) + call discretization_setIPcoords (reshape(x_p,[3,cells(1)*cells(2)*cells3])) end subroutine utilities_updateCoords @@ -1178,22 +1125,22 @@ subroutine selfTest() scalarField_real_ = spread(spread(planeCosine(cells(1)),2,cells(2)),3,cells3) vectorField_real_ = utilities_scalarGradient(scalarField_real_)/TAU*geomSize(1) scalarField_real_ = -spread(spread(planeSine (cells(1)),2,cells(2)),3,cells3) - if (maxval(abs(vectorField_real_(1,:,:,:) - scalarField_real_))>5.0e-14_pReal) error stop 'grad cosine' + if (maxval(abs(vectorField_real_(1,:,:,:) - scalarField_real_))>5.0e-12_pReal) error stop 'grad cosine' scalarField_real_ = spread(spread(planeSine (cells(1)),2,cells(2)),3,cells3) vectorField_real_ = utilities_scalarGradient(scalarField_real_)/TAU*geomSize(1) scalarField_real_ = spread(spread(planeCosine(cells(1)),2,cells(2)),3,cells3) - if (maxval(abs(vectorField_real_(1,:,:,:) - scalarField_real_))>5.0e-14_pReal) error stop 'grad sine' + if (maxval(abs(vectorField_real_(1,:,:,:) - scalarField_real_))>5.0e-12_pReal) error stop 'grad sine' vectorField_real_(2:3,:,:,:) = 0.0_pReal vectorField_real_(1,:,:,:) = spread(spread(planeCosine(cells(1)),2,cells(2)),3,cells3) scalarField_real_ = utilities_vectorDivergence(vectorField_real_)/TAU*geomSize(1) vectorField_real_(1,:,:,:) =-spread(spread(planeSine( cells(1)),2,cells(2)),3,cells3) - if (maxval(abs(vectorField_real_(1,:,:,:) - scalarField_real_))>5.0e-14_pReal) error stop 'div cosine' + if (maxval(abs(vectorField_real_(1,:,:,:) - scalarField_real_))>5.0e-12_pReal) error stop 'div cosine' vectorField_real_(2:3,:,:,:) = 0.0_pReal vectorField_real_(1,:,:,:) = spread(spread(planeSine( cells(1)),2,cells(2)),3,cells3) scalarField_real_ = utilities_vectorDivergence(vectorField_real_)/TAU*geomSize(1) vectorField_real_(1,:,:,:) = spread(spread(planeCosine(cells(1)),2,cells(2)),3,cells3) - if (maxval(abs(vectorField_real_(1,:,:,:) - scalarField_real_))>5.0e-14_pReal) error stop 'div sine' + if (maxval(abs(vectorField_real_(1,:,:,:) - scalarField_real_))>5.0e-12_pReal) error stop 'div sine' end if contains diff --git a/src/homogenization.f90 b/src/homogenization.f90 index 2c89a1859..778a094b4 100644 --- a/src/homogenization.f90 +++ b/src/homogenization.f90 @@ -15,7 +15,7 @@ module homogenization use discretization use HDF5 use HDF5_utilities - use results + use result use lattice implicit none(type,external) @@ -101,20 +101,20 @@ module homogenization ce !< cell end subroutine mechanical_homogenize - module subroutine mechanical_results(group_base,ho) + module subroutine mechanical_result(group_base,ho) character(len=*), intent(in) :: group_base integer, intent(in) :: ho - end subroutine mechanical_results + end subroutine mechanical_result - module subroutine damage_results(ho,group) + module subroutine damage_result(ho,group) integer, intent(in) :: ho character(len=*), intent(in) :: group - end subroutine damage_results + end subroutine damage_result - module subroutine thermal_results(ho,group) + module subroutine thermal_result(ho,group) integer, intent(in) :: ho character(len=*), intent(in) :: group - end subroutine thermal_results + end subroutine thermal_result module function mechanical_updateState(subdt,subF,ce) result(doneAndHappy) real(pReal), intent(in) :: & @@ -194,7 +194,7 @@ module homogenization homogenization_f_phi, & homogenization_set_phi, & homogenization_forward, & - homogenization_results, & + homogenization_result, & homogenization_restartRead, & homogenization_restartWrite @@ -250,8 +250,8 @@ subroutine homogenization_mechanical_response(Delta_t,cell_start,cell_end) !$OMP PARALLEL DO PRIVATE(en,ho,co,NiterationMPstate,converged,doneAndHappy) do ce = cell_start, cell_end - en = material_homogenizationEntry(ce) - ho = material_homogenizationID(ce) + en = material_entry_homogenization(ce) + ho = material_ID_homogenization(ce) call phase_restore(ce,.false.) ! wrong name (is more a forward function) @@ -303,9 +303,9 @@ subroutine homogenization_thermal_response(Delta_t,cell_start,cell_end) !$OMP PARALLEL DO PRIVATE(ho) do ce = cell_start, cell_end if (terminallyIll) continue - ho = material_homogenizationID(ce) + ho = material_ID_homogenization(ce) do co = 1, homogenization_Nconstituents(ho) - if (.not. phase_thermal_constitutive(Delta_t,material_phaseID(co,ce),material_phaseEntry(co,ce))) then + if (.not. phase_thermal_constitutive(Delta_t,material_ID_phase(co,ce),material_entry_phase(co,ce))) then if (.not. terminallyIll) print*, ' Cell ', ce, ' terminally ill' terminallyIll = .true. end if @@ -333,7 +333,7 @@ subroutine homogenization_mechanical_response2(Delta_t,FEsolving_execIP,FEsolvin elementLooping3: do el = FEsolving_execElem(1),FEsolving_execElem(2) IpLooping3: do ip = FEsolving_execIP(1),FEsolving_execIP(2) ce = (el-1)*discretization_nIPs + ip - ho = material_homogenizationID(ce) + ho = material_ID_homogenization(ce) do co = 1, homogenization_Nconstituents(ho) call crystallite_orientations(co,ip,el) end do @@ -349,35 +349,35 @@ end subroutine homogenization_mechanical_response2 !-------------------------------------------------------------------------------------------------- !> @brief writes homogenization results to HDF5 output file !-------------------------------------------------------------------------------------------------- -subroutine homogenization_results +subroutine homogenization_result integer :: ho character(len=:), allocatable :: group_base,group - call results_closeGroup(results_addGroup('current/homogenization/')) + call result_closeGroup(result_addGroup('current/homogenization/')) do ho=1,size(material_name_homogenization) group_base = 'current/homogenization/'//trim(material_name_homogenization(ho)) - call results_closeGroup(results_addGroup(group_base)) + call result_closeGroup(result_addGroup(group_base)) - call mechanical_results(group_base,ho) + call mechanical_result(group_base,ho) if (damage_active(ho)) then group = trim(group_base)//'/damage' - call results_closeGroup(results_addGroup(group)) - call damage_results(ho,group) + call result_closeGroup(result_addGroup(group)) + call damage_result(ho,group) end if if (thermal_active(ho)) then group = trim(group_base)//'/thermal' - call results_closeGroup(results_addGroup(group)) - call thermal_results(ho,group) + call result_closeGroup(result_addGroup(group)) + call thermal_result(ho,group) end if end do -end subroutine homogenization_results +end subroutine homogenization_result !-------------------------------------------------------------------------------------------------- diff --git a/src/homogenization_damage.f90 b/src/homogenization_damage.f90 index 40c85cd2b..703f546d0 100644 --- a/src/homogenization_damage.f90 +++ b/src/homogenization_damage.f90 @@ -47,7 +47,7 @@ module subroutine damage_init() allocate(current(configHomogenizations%length)) do ho = 1, configHomogenizations%length - Nmembers = count(material_homogenizationID == ho) + Nmembers = count(material_ID_homogenization == ho) allocate(current(ho)%phi(Nmembers), source=1.0_pReal) configHomogenization => configHomogenizations%get_dict(ho) associate(prm => param(ho)) @@ -95,9 +95,9 @@ module subroutine damage_partition(ce) integer :: co - if (damageState_h(material_homogenizationID(ce))%sizeState < 1) return - phi = damagestate_h(material_homogenizationID(ce))%state(1,material_homogenizationEntry(ce)) - do co = 1, homogenization_Nconstituents(material_homogenizationID(ce)) + if (damageState_h(material_ID_homogenization(ce))%sizeState < 1) return + phi = damagestate_h(material_ID_homogenization(ce))%state(1,material_entry_homogenization(ce)) + do co = 1, homogenization_Nconstituents(material_ID_homogenization(ce)) call phase_set_phi(phi,co,ce) end do @@ -161,8 +161,8 @@ module subroutine homogenization_set_phi(phi,ce) en - ho = material_homogenizationID(ce) - en = material_homogenizationEntry(ce) + ho = material_ID_homogenization(ce) + en = material_entry_homogenization(ce) damagestate_h(ho)%state(1,en) = phi current(ho)%phi(en) = phi @@ -172,7 +172,7 @@ end subroutine homogenization_set_phi !-------------------------------------------------------------------------------------------------- !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -module subroutine damage_results(ho,group) +module subroutine damage_result(ho,group) integer, intent(in) :: ho character(len=*), intent(in) :: group @@ -184,12 +184,12 @@ module subroutine damage_results(ho,group) outputsLoop: do o = 1,size(prm%output) select case(prm%output(o)) case ('phi') - call results_writeDataset(current(ho)%phi,group,prm%output(o),& - 'damage indicator','-') + call result_writeDataset(current(ho)%phi,group,prm%output(o),& + 'damage indicator','-') end select end do outputsLoop end associate -end subroutine damage_results +end subroutine damage_result end submodule damage diff --git a/src/homogenization_mechanical.f90 b/src/homogenization_mechanical.f90 index 5c93da7be..24625769e 100644 --- a/src/homogenization_mechanical.f90 +++ b/src/homogenization_mechanical.f90 @@ -43,10 +43,10 @@ submodule(homogenization) mechanical end function RGC_updateState - module subroutine RGC_results(ho,group) + module subroutine RGC_result(ho,group) integer, intent(in) :: ho !< homogenization type character(len=*), intent(in) :: group !< group name in HDF5 file - end subroutine RGC_results + end subroutine RGC_result end interface @@ -99,10 +99,10 @@ module subroutine mechanical_partition(subF,ce) ce integer :: co - real(pReal), dimension (3,3,homogenization_Nconstituents(material_homogenizationID(ce))) :: Fs + real(pReal), dimension (3,3,homogenization_Nconstituents(material_ID_homogenization(ce))) :: Fs - chosenHomogenization: select case(mechanical_type(material_homogenizationID(ce))) + chosenHomogenization: select case(mechanical_type(material_ID_homogenization(ce))) case (MECHANICAL_PASS_ID) chosenHomogenization Fs(1:3,1:3,1) = subF @@ -115,7 +115,7 @@ module subroutine mechanical_partition(subF,ce) end select chosenHomogenization - do co = 1,homogenization_Nconstituents(material_homogenizationID(ce)) + do co = 1,homogenization_Nconstituents(material_ID_homogenization(ce)) call phase_set_F(Fs(1:3,1:3,co),co,ce) end do @@ -136,7 +136,7 @@ module subroutine mechanical_homogenize(Delta_t,ce) homogenization_P(1:3,1:3,ce) = phase_P(1,ce)*material_v(1,ce) homogenization_dPdF(1:3,1:3,1:3,1:3,ce) = phase_mechanical_dPdF(Delta_t,1,ce)*material_v(1,ce) - do co = 2, homogenization_Nconstituents(material_homogenizationID(ce)) + do co = 2, homogenization_Nconstituents(material_ID_homogenization(ce)) homogenization_P(1:3,1:3,ce) = homogenization_P(1:3,1:3,ce) & + phase_P(co,ce)*material_v(co,ce) homogenization_dPdF(1:3,1:3,1:3,1:3,ce) = homogenization_dPdF(1:3,1:3,1:3,1:3,ce) & @@ -161,13 +161,13 @@ module function mechanical_updateState(subdt,subF,ce) result(doneAndHappy) logical, dimension(2) :: doneAndHappy integer :: co - real(pReal) :: dPdFs(3,3,3,3,homogenization_Nconstituents(material_homogenizationID(ce))) - real(pReal) :: Fs(3,3,homogenization_Nconstituents(material_homogenizationID(ce))) - real(pReal) :: Ps(3,3,homogenization_Nconstituents(material_homogenizationID(ce))) + real(pReal) :: dPdFs(3,3,3,3,homogenization_Nconstituents(material_ID_homogenization(ce))) + real(pReal) :: Fs(3,3,homogenization_Nconstituents(material_ID_homogenization(ce))) + real(pReal) :: Ps(3,3,homogenization_Nconstituents(material_ID_homogenization(ce))) - if (mechanical_type(material_homogenizationID(ce)) == MECHANICAL_RGC_ID) then - do co = 1, homogenization_Nconstituents(material_homogenizationID(ce)) + if (mechanical_type(material_ID_homogenization(ce)) == MECHANICAL_RGC_ID) then + do co = 1, homogenization_Nconstituents(material_ID_homogenization(ce)) dPdFs(:,:,:,:,co) = phase_mechanical_dPdF(subdt,co,ce) Fs(:,:,co) = phase_F(co,ce) Ps(:,:,co) = phase_P(co,ce) @@ -183,7 +183,7 @@ end function mechanical_updateState !-------------------------------------------------------------------------------------------------- !> @brief Write results to file. !-------------------------------------------------------------------------------------------------- -module subroutine mechanical_results(group_base,ho) +module subroutine mechanical_result(group_base,ho) character(len=*), intent(in) :: group_base integer, intent(in) :: ho @@ -193,12 +193,12 @@ module subroutine mechanical_results(group_base,ho) group = trim(group_base)//'/mechanical' - call results_closeGroup(results_addGroup(group)) + call result_closeGroup(result_addGroup(group)) select case(mechanical_type(ho)) case(MECHANICAL_RGC_ID) - call RGC_results(ho,group) + call RGC_result(ho,group) end select @@ -206,15 +206,15 @@ module subroutine mechanical_results(group_base,ho) select case (output_mechanical(ho)%label(ou)) case('F') - call results_writeDataset(reshape(homogenization_F,[3,3,discretization_nCells]),group,'F', & - 'deformation gradient','1') + call result_writeDataset(reshape(homogenization_F,[3,3,discretization_nCells]),group,'F', & + 'deformation gradient','1') case('P') - call results_writeDataset(reshape(homogenization_P,[3,3,discretization_nCells]),group,'P', & - 'first Piola-Kirchhoff stress','Pa') + call result_writeDataset(reshape(homogenization_P,[3,3,discretization_nCells]),group,'P', & + 'first Piola-Kirchhoff stress','Pa') end select end do -end subroutine mechanical_results +end subroutine mechanical_result !-------------------------------------------------------------------------------------------------- diff --git a/src/homogenization_mechanical_RGC.f90 b/src/homogenization_mechanical_RGC.f90 index bc2fd71cf..0e85fcca6 100644 --- a/src/homogenization_mechanical_RGC.f90 +++ b/src/homogenization_mechanical_RGC.f90 @@ -162,7 +162,7 @@ module subroutine RGC_init() prm%D_alpha = homogMech%get_as1dFloat('D_alpha', requiredSize=3) prm%a_g = homogMech%get_as1dFloat('a_g', requiredSize=3) - Nmembers = count(material_homogenizationID == ho) + Nmembers = count(material_ID_homogenization == ho) nIntFaceTot = 3*( (prm%N_constituents(1)-1)*prm%N_constituents(2)*prm%N_constituents(3) & + prm%N_constituents(1)*(prm%N_constituents(2)-1)*prm%N_constituents(3) & + prm%N_constituents(1)*prm%N_constituents(2)*(prm%N_constituents(3)-1)) @@ -208,10 +208,10 @@ module subroutine RGC_partitionDeformation(F,avgF,ce) integer, dimension(3) :: iGrain3 integer :: iGrain,iFace,i,j,ho,en - associate(prm => param(material_homogenizationID(ce))) + associate(prm => param(material_ID_homogenization(ce))) - ho = material_homogenizationID(ce) - en = material_homogenizationEntry(ce) + ho = material_ID_homogenization(ce) + en = material_entry_homogenization(ce) !-------------------------------------------------------------------------------------------------- ! compute the deformation gradient of individual grains due to relaxations F = 0.0_pReal @@ -263,8 +263,8 @@ module function RGC_updateState(P,F,avgF,dt,dPdF,ce) result(doneAndHappy) return end if zeroTimeStep - ho = material_homogenizationID(ce) - en = material_homogenizationEntry(ce) + ho = material_ID_homogenization(ce) + en = material_entry_homogenization(ce) associate(stt => state(ho), st0 => state0(ho), dst => dependentState(ho), prm => param(ho)) @@ -652,7 +652,7 @@ module function RGC_updateState(P,F,avgF,dt,dPdF,ce) result(doneAndHappy) real(pReal), dimension(6,6) :: C - C = phase_homogenizedC66(material_phaseID(co,ce),material_phaseEntry(co,ce)) ! damage not included! + C = phase_homogenizedC66(material_ID_phase(co,ce),material_entry_phase(co,ce)) ! damage not included! equivalentMu = lattice_isotropic_mu(C,'isostrain') @@ -705,7 +705,7 @@ end function RGC_updateState !-------------------------------------------------------------------------------------------------- !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -module subroutine RGC_results(ho,group) +module subroutine RGC_result(ho,group) integer, intent(in) :: ho character(len=*), intent(in) :: group @@ -713,25 +713,25 @@ module subroutine RGC_results(ho,group) integer :: o associate(stt => state(ho), dst => dependentState(ho), prm => param(ho)) - outputsLoop: do o = 1,size(prm%output) - select case(trim(prm%output(o))) - case('M') - call results_writeDataset(dst%mismatch,group,trim(prm%output(o)), & - 'average mismatch tensor','1') - case('Delta_V') - call results_writeDataset(dst%volumeDiscrepancy,group,trim(prm%output(o)), & - 'volume discrepancy','m³') - case('max_dot_a') - call results_writeDataset(dst%relaxationrate_max,group,trim(prm%output(o)), & - 'maximum relaxation rate','m/s') - case('avg_dot_a') - call results_writeDataset(dst%relaxationrate_avg,group,trim(prm%output(o)), & - 'average relaxation rate','m/s') - end select - end do outputsLoop + outputsLoop: do o = 1,size(prm%output) + select case(trim(prm%output(o))) + case('M') + call result_writeDataset(dst%mismatch,group,trim(prm%output(o)), & + 'average mismatch tensor','1') + case('Delta_V') + call result_writeDataset(dst%volumeDiscrepancy,group,trim(prm%output(o)), & + 'volume discrepancy','m³') + case('max_dot_a') + call result_writeDataset(dst%relaxationrate_max,group,trim(prm%output(o)), & + 'maximum relaxation rate','m/s') + case('avg_dot_a') + call result_writeDataset(dst%relaxationrate_avg,group,trim(prm%output(o)), & + 'average relaxation rate','m/s') + end select + end do outputsLoop end associate -end subroutine RGC_results +end subroutine RGC_result !-------------------------------------------------------------------------------------------------- diff --git a/src/homogenization_mechanical_isostrain.f90 b/src/homogenization_mechanical_isostrain.f90 index 72aed0166..3a603196f 100644 --- a/src/homogenization_mechanical_isostrain.f90 +++ b/src/homogenization_mechanical_isostrain.f90 @@ -25,7 +25,7 @@ module subroutine isostrain_init do ho = 1, size(mechanical_type) if (mechanical_type(ho) /= MECHANICAL_ISOSTRAIN_ID) cycle - Nmembers = count(material_homogenizationID == ho) + Nmembers = count(material_ID_homogenization == ho) homogState(ho)%sizeState = 0 allocate(homogState(ho)%state0(0,Nmembers)) allocate(homogState(ho)%state (0,Nmembers)) diff --git a/src/homogenization_mechanical_pass.f90 b/src/homogenization_mechanical_pass.f90 index 38d961562..f3c79107f 100644 --- a/src/homogenization_mechanical_pass.f90 +++ b/src/homogenization_mechanical_pass.f90 @@ -28,7 +28,7 @@ module subroutine pass_init() if (homogenization_Nconstituents(ho) /= 1) & call IO_error(211,ext_msg='(pass) with N_constituents !=1') - Nmembers = count(material_homogenizationID == ho) + Nmembers = count(material_ID_homogenization == ho) homogState(ho)%sizeState = 0 allocate(homogState(ho)%state0(0,Nmembers)) allocate(homogState(ho)%state (0,Nmembers)) diff --git a/src/homogenization_thermal.f90 b/src/homogenization_thermal.f90 index 274c392e8..edba596c8 100644 --- a/src/homogenization_thermal.f90 +++ b/src/homogenization_thermal.f90 @@ -50,8 +50,8 @@ module subroutine thermal_init() allocate(current(configHomogenizations%length)) do ho = 1, configHomogenizations%length - allocate(current(ho)%T(count(material_homogenizationID==ho)), source=T_ROOM) - allocate(current(ho)%dot_T(count(material_homogenizationID==ho)), source=0.0_pReal) + allocate(current(ho)%T(count(material_ID_homogenization==ho)), source=T_ROOM) + allocate(current(ho)%dot_T(count(material_ID_homogenization==ho)), source=0.0_pReal) configHomogenization => configHomogenizations%get_dict(ho) associate(prm => param(ho)) @@ -104,9 +104,9 @@ module subroutine thermal_partition(ce) integer :: co - T = current(material_homogenizationID(ce))%T(material_homogenizationEntry(ce)) - dot_T = current(material_homogenizationID(ce))%dot_T(material_homogenizationEntry(ce)) - do co = 1, homogenization_Nconstituents(material_homogenizationID(ce)) + T = current(material_ID_homogenization(ce))%T(material_entry_homogenization(ce)) + dot_T = current(material_ID_homogenization(ce))%dot_T(material_entry_homogenization(ce)) + do co = 1, homogenization_Nconstituents(material_ID_homogenization(ce)) call phase_thermal_setField(T,dot_T,co,ce) end do @@ -125,7 +125,7 @@ module function homogenization_mu_T(ce) result(mu) mu = phase_mu_T(1,ce)*material_v(1,ce) - do co = 2, homogenization_Nconstituents(material_homogenizationID(ce)) + do co = 2, homogenization_Nconstituents(material_ID_homogenization(ce)) mu = mu + phase_mu_T(co,ce)*material_v(co,ce) end do @@ -144,7 +144,7 @@ module function homogenization_K_T(ce) result(K) K = phase_K_T(1,ce)*material_v(1,ce) - do co = 2, homogenization_Nconstituents(material_homogenizationID(ce)) + do co = 2, homogenization_Nconstituents(material_ID_homogenization(ce)) K = K + phase_K_T(co,ce)*material_v(co,ce) end do @@ -162,9 +162,9 @@ module function homogenization_f_T(ce) result(f) integer :: co - f = phase_f_T(material_phaseID(1,ce),material_phaseEntry(1,ce))*material_v(1,ce) - do co = 2, homogenization_Nconstituents(material_homogenizationID(ce)) - f = f + phase_f_T(material_phaseID(co,ce),material_phaseEntry(co,ce))*material_v(co,ce) + f = phase_f_T(material_ID_phase(1,ce),material_entry_phase(1,ce))*material_v(1,ce) + do co = 2, homogenization_Nconstituents(material_ID_homogenization(ce)) + f = f + phase_f_T(material_ID_phase(co,ce),material_entry_phase(co,ce))*material_v(co,ce) end do end function homogenization_f_T @@ -179,8 +179,8 @@ module subroutine homogenization_thermal_setField(T,dot_T, ce) real(pReal), intent(in) :: T, dot_T - current(material_homogenizationID(ce))%T(material_homogenizationEntry(ce)) = T - current(material_homogenizationID(ce))%dot_T(material_homogenizationEntry(ce)) = dot_T + current(material_ID_homogenization(ce))%T(material_entry_homogenization(ce)) = T + current(material_ID_homogenization(ce))%dot_T(material_entry_homogenization(ce)) = dot_T call thermal_partition(ce) end subroutine homogenization_thermal_setField @@ -189,7 +189,7 @@ end subroutine homogenization_thermal_setField !-------------------------------------------------------------------------------------------------- !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -module subroutine thermal_results(ho,group) +module subroutine thermal_result(ho,group) integer, intent(in) :: ho character(len=*), intent(in) :: group @@ -201,11 +201,11 @@ module subroutine thermal_results(ho,group) outputsLoop: do o = 1,size(prm%output) select case(trim(prm%output(o))) case('T') - call results_writeDataset(current(ho)%T,group,'T','temperature','K') + call result_writeDataset(current(ho)%T,group,'T','temperature','K') end select end do outputsLoop end associate -end subroutine thermal_results +end subroutine thermal_result end submodule thermal diff --git a/src/lattice.f90 b/src/lattice.f90 index beded840b..5cb254012 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -8,6 +8,7 @@ !-------------------------------------------------------------------------------------------------- module lattice use prec + use misc use IO use config use math @@ -2159,12 +2160,8 @@ pure function lattice_isotropic_nu(C,assumption,lattice) result(nu) real(pReal) :: K, mu logical :: error real(pReal), dimension(6,6) :: S - character(len=:), allocatable :: lattice_ - lattice_ = IO_WHITESPACE - if (present(lattice)) lattice_ = lattice - if (IO_lc(assumption) == 'isostrain') then K = sum(C(1:3,1:3)) / 9.0_pReal elseif (IO_lc(assumption) == 'isostress') then @@ -2175,7 +2172,7 @@ pure function lattice_isotropic_nu(C,assumption,lattice) result(nu) error stop 'invalid assumption' end if - mu = lattice_isotropic_mu(C,assumption,lattice_) + mu = lattice_isotropic_mu(C,assumption,lattice) nu = (1.5_pReal*K-mu)/(3.0_pReal*K+mu) end function lattice_isotropic_nu @@ -2195,14 +2192,10 @@ pure function lattice_isotropic_mu(C,assumption,lattice) result(mu) logical :: error real(pReal), dimension(6,6) :: S - character(len=:), allocatable :: lattice_ - lattice_ = IO_WHITESPACE - if (present(lattice)) lattice_ = lattice - if (IO_lc(assumption) == 'isostrain') then - select case(lattice_) + select case(misc_optional(lattice,'')) case('cF','cI') mu = ( C(1,1) - C(1,2) + C(4,4)*3.0_pReal) / 5.0_pReal case default @@ -2213,7 +2206,7 @@ pure function lattice_isotropic_mu(C,assumption,lattice) result(mu) end select elseif (IO_lc(assumption) == 'isostress') then - select case(lattice_) + select case(misc_optional(lattice,'')) case('cF','cI') mu = 5.0_pReal & / (4.0_pReal/(C(1,1)-C(1,2)) + 3.0_pReal/C(4,4)) diff --git a/src/material.f90 b/src/material.f90 index d1d9ca43e..2169c876a 100644 --- a/src/material.f90 +++ b/src/material.f90 @@ -7,7 +7,7 @@ module material use prec use config - use results + use result use math use IO use rotations @@ -39,11 +39,11 @@ module material material_name_homogenization !< name of each homogenization integer, dimension(:), allocatable, public, protected :: & ! (cell) - material_homogenizationID, & ! TODO: rename to material_ID_homogenization - material_homogenizationEntry ! TODO: rename to material_entry_homogenization + material_ID_homogenization, & !< Number of the homogenization + material_entry_homogenization !< Position in array of used homogenization integer, dimension(:,:), allocatable, public, protected :: & ! (constituent,cell) - material_phaseID, & ! TODO: rename to material_ID_phase - material_phaseEntry ! TODO: rename to material_entry_phase + material_ID_phase, & !< Number of the phase + material_entry_phase !< Position in array of used phase real(pReal), dimension(:,:), allocatable, public, protected :: & material_v ! fraction @@ -69,17 +69,17 @@ subroutine material_init(restart) if (.not. restart) then - call results_openJobFile - call results_mapping_phase(material_phaseID,material_phaseEntry,material_name_phase) - call results_mapping_homogenization(material_homogenizationID,material_homogenizationEntry,material_name_homogenization) - call results_closeJobFile + call result_openJobFile() + call result_mapping_phase(material_ID_phase,material_entry_phase,material_name_phase) + call result_mapping_homogenization(material_ID_homogenization,material_entry_homogenization,material_name_homogenization) + call result_closeJobFile() end if end subroutine material_init !-------------------------------------------------------------------------------------------------- -!> @brief Parse material.yaml to get the global structure +!> @brief Parse material.yaml to get the global structure. !-------------------------------------------------------------------------------------------------- subroutine parse() @@ -166,11 +166,11 @@ subroutine parse() allocate(counterPhase(phases%length),source=0) allocate(counterHomogenization(homogenizations%length),source=0) - allocate(material_homogenizationID(discretization_Ncells),source=0) - allocate(material_homogenizationEntry(discretization_Ncells),source=0) + allocate(material_ID_homogenization(discretization_Ncells),source=0) + allocate(material_entry_homogenization(discretization_Ncells),source=0) - allocate(material_phaseID(homogenization_maxNconstituents,discretization_Ncells),source=0) - allocate(material_phaseEntry(homogenization_maxNconstituents,discretization_Ncells),source=0) + allocate(material_ID_phase(homogenization_maxNconstituents,discretization_Ncells),source=0) + allocate(material_entry_phase(homogenization_maxNconstituents,discretization_Ncells),source=0) ! build mappings @@ -181,9 +181,9 @@ subroutine parse() do ip = 1, discretization_nIPs ce = (el-1)*discretization_nIPs + ip - material_homogenizationID(ce) = ho + material_ID_homogenization(ce) = ho counterHomogenization(ho) = counterHomogenization(ho) + 1 - material_homogenizationEntry(ce) = counterHomogenization(ho) + material_entry_homogenization(ce) = counterHomogenization(ho) end do do co = 1, size(ph_of(ma,:)>0) @@ -193,9 +193,9 @@ subroutine parse() do ip = 1, discretization_nIPs ce = (el-1)*discretization_nIPs + ip - material_phaseID(co,ce) = ph + material_ID_phase(co,ce) = ph counterPhase(ph) = counterPhase(ph) + 1 - material_phaseEntry(co,ce) = counterPhase(ph) + material_entry_phase(co,ce) = counterPhase(ph) material_v(co,ce) = v end do diff --git a/src/materialpoint.f90 b/src/materialpoint.f90 index 8ce0e15a1..dda2e5870 100644 --- a/src/materialpoint.f90 +++ b/src/materialpoint.f90 @@ -5,15 +5,16 @@ !-------------------------------------------------------------------------------------------------- module materialpoint use parallelization - use signals + use signal use CLI use prec + use misc use IO use YAML_types use YAML_parse use HDF5 use HDF5_utilities - use results + use result use config use math use rotations @@ -45,8 +46,9 @@ subroutine materialpoint_initAll() call parallelization_init() call CLI_init() ! grid and mesh commandline interface - call signals_init() + call signal_init() call prec_init() + call misc_init() call IO_init() #if defined(MESH) call FEM_quadrature_init() @@ -56,7 +58,7 @@ subroutine materialpoint_initAll() call YAML_types_init() call YAML_parse_init() call HDF5_utilities_init() - call results_init(restart=CLI_restartInc>0) + call result_init(restart=CLI_restartInc>0) call config_init() call math_init() call rotations_init() @@ -72,7 +74,7 @@ subroutine materialpoint_initAll() call phase_init() call homogenization_init() call materialpoint_init() - call config_deallocate() + call config_material_deallocate() end subroutine materialpoint_initAll @@ -136,19 +138,19 @@ end subroutine materialpoint_forward !-------------------------------------------------------------------------------------------------- !> @brief Trigger writing of results. !-------------------------------------------------------------------------------------------------- -subroutine materialpoint_results(inc,time) +subroutine materialpoint_result(inc,time) integer, intent(in) :: inc real(pReal), intent(in) :: time - call results_openJobFile() - call results_addIncrement(inc,time) - call phase_results() - call homogenization_results() - call discretization_results() - call results_finalizeIncrement() - call results_closeJobFile() + call result_openJobFile() + call result_addIncrement(inc,time) + call phase_result() + call homogenization_result() + call discretization_result() + call result_finalizeIncrement() + call result_closeJobFile() -end subroutine materialpoint_results +end subroutine materialpoint_result end module materialpoint diff --git a/src/math.f90 b/src/math.f90 index ff0c604b3..3c1f5b608 100644 --- a/src/math.f90 +++ b/src/math.f90 @@ -7,6 +7,7 @@ !-------------------------------------------------------------------------------------------------- module math use prec + use misc use IO use config use YAML_types @@ -140,23 +141,9 @@ pure recursive subroutine math_sort(a, istart, iend, sortDim) integer :: ipivot,s,e,d - if (present(istart)) then - s = istart - else - s = lbound(a,2) - end if - - if (present(iend)) then - e = iend - else - e = ubound(a,2) - end if - - if (present(sortDim)) then - d = sortDim - else - d = 1 - end if + s = misc_optional(istart,lbound(a,2)) + e = misc_optional(iend,ubound(a,2)) + d = misc_optional(sortDim,1) if (s < e) then call qsort_partition(a,ipivot, s,e, d) @@ -448,20 +435,14 @@ pure function math_exp33(A,n) real(pReal), dimension(3,3) :: B, math_exp33 real(pReal) :: invFac - integer :: n_,i + integer :: i - if (present(n)) then - n_ = n - else - n_ = 5 - end if - invFac = 1.0_pReal ! 0! B = math_I3 math_exp33 = math_I3 ! A^0 = I - do i = 1, n_ + do i = 1, misc_optional(n,5) invFac = invFac/real(i,pReal) ! invfac = 1/(i!) B = matmul(B,A) math_exp33 = math_exp33 + invFac*B ! exp = SUM (A^i)/(i!) @@ -533,7 +514,7 @@ end subroutine math_invert33 !-------------------------------------------------------------------------------------------------- -!> @brief Inversion of symmetriced 3x3x3x3 matrix +!> @brief Invert symmetriced 3x3x3x3 matrix. !-------------------------------------------------------------------------------------------------- pure function math_invSym3333(A) @@ -549,7 +530,7 @@ pure function math_invSym3333(A) temp66 = math_sym3333to66(A) call dgetrf(6,6,temp66,6,ipiv6,ierr_i) - call dgetri(6,temp66,6,ipiv6,work,size(work,1),ierr_f) + call dgetri(6,temp66,6,ipiv6,work,size(work),ierr_f) if (ierr_i /= 0 .or. ierr_f /= 0) then error stop 'matrix inversion error' else @@ -560,7 +541,7 @@ end function math_invSym3333 !-------------------------------------------------------------------------------------------------- -!> @brief invert quadratic matrix of arbitrary dimension +!> @brief Invert quadratic matrix of arbitrary dimension. !-------------------------------------------------------------------------------------------------- pure subroutine math_invert(InvA, error, A) @@ -576,14 +557,14 @@ pure subroutine math_invert(InvA, error, A) invA = A call dgetrf(size(A,1),size(A,1),invA,size(A,1),ipiv,ierr) error = (ierr /= 0) - call dgetri(size(A,1),InvA,size(A,1),ipiv,work,size(work,1),ierr) + call dgetri(size(A,1),InvA,size(A,1),ipiv,work,size(work),ierr) error = error .or. (ierr /= 0) end subroutine math_invert !-------------------------------------------------------------------------------------------------- -!> @brief symmetrize a 3x3 matrix +!> @brief Symmetrize a 3x3 matrix. !-------------------------------------------------------------------------------------------------- pure function math_symmetric33(m) @@ -597,7 +578,7 @@ end function math_symmetric33 !-------------------------------------------------------------------------------------------------- -!> @brief skew part of a 3x3 matrix +!> @brief Calculate skew part of a 3x3 matrix. !-------------------------------------------------------------------------------------------------- pure function math_skew33(m) @@ -611,7 +592,7 @@ end function math_skew33 !-------------------------------------------------------------------------------------------------- -!> @brief hydrostatic part of a 3x3 matrix +!> @brief Calculate hydrostatic part of a 3x3 matrix. !-------------------------------------------------------------------------------------------------- pure function math_spherical33(m) @@ -625,7 +606,7 @@ end function math_spherical33 !-------------------------------------------------------------------------------------------------- -!> @brief deviatoric part of a 3x3 matrix +!> @brief Calculate deviatoric part of a 3x3 matrix. !-------------------------------------------------------------------------------------------------- pure function math_deviatoric33(m) @@ -639,7 +620,7 @@ end function math_deviatoric33 !-------------------------------------------------------------------------------------------------- -!> @brief trace of a 3x3 matrix +!> @brief Calculate trace of a 3x3 matrix. !-------------------------------------------------------------------------------------------------- real(pReal) pure function math_trace33(m) @@ -652,7 +633,7 @@ end function math_trace33 !-------------------------------------------------------------------------------------------------- -!> @brief determinant of a 3x3 matrix +!> @brief Calculate determinant of a 3x3 matrix. !-------------------------------------------------------------------------------------------------- real(pReal) pure function math_det33(m) @@ -667,7 +648,7 @@ end function math_det33 !-------------------------------------------------------------------------------------------------- -!> @brief determinant of a symmetric 3x3 matrix +!> @brief Calculate determinant of a symmetric 3x3 matrix. !-------------------------------------------------------------------------------------------------- real(pReal) pure function math_detSym33(m) @@ -681,7 +662,7 @@ end function math_detSym33 !-------------------------------------------------------------------------------------------------- -!> @brief convert 3x3 matrix into vector 9 +!> @brief Convert 3x3 matrix into 9 vector. !-------------------------------------------------------------------------------------------------- pure function math_33to9(m33) @@ -697,7 +678,7 @@ end function math_33to9 !-------------------------------------------------------------------------------------------------- -!> @brief convert 9 vector into 3x3 matrix +!> @brief Convert 9 vector into 3x3 matrix. !-------------------------------------------------------------------------------------------------- pure function math_9to33(v9) @@ -715,7 +696,7 @@ end function math_9to33 !-------------------------------------------------------------------------------------------------- -!> @brief convert symmetric 3x3 matrix into 6 vector +!> @brief Convert symmetric 3x3 matrix into 6 vector. !> @details Weighted conversion (default) rearranges according to Nye and weights shear ! components according to Mandel. Advisable for matrix operations. ! Unweighted conversion only changes order according to Nye @@ -729,12 +710,7 @@ pure function math_sym33to6(m33,weighted) real(pReal), dimension(6) :: w integer :: i - - if (present(weighted)) then - w = merge(NRMMANDEL,1.0_pReal,weighted) - else - w = NRMMANDEL - end if + w = merge(NRMMANDEL,1.0_pReal,misc_optional(weighted,.true.)) math_sym33to6 = [(w(i)*m33(MAPNYE(1,i),MAPNYE(2,i)),i=1,6)] @@ -742,7 +718,7 @@ end function math_sym33to6 !-------------------------------------------------------------------------------------------------- -!> @brief convert 6 vector into symmetric 3x3 matrix +!> @brief Convert 6 vector into symmetric 3x3 matrix. !> @details Weighted conversion (default) rearranges according to Nye and weights shear ! components according to Mandel. Advisable for matrix operations. ! Unweighted conversion only changes order according to Nye @@ -757,11 +733,7 @@ pure function math_6toSym33(v6,weighted) integer :: i - if (present(weighted)) then - w = merge(INVNRMMANDEL,1.0_pReal,weighted) - else - w = INVNRMMANDEL - end if + w = merge(INVNRMMANDEL,1.0_pReal,misc_optional(weighted,.true.)) do i=1,6 math_6toSym33(MAPNYE(1,i),MAPNYE(2,i)) = w(i)*v6(i) @@ -772,7 +744,7 @@ end function math_6toSym33 !-------------------------------------------------------------------------------------------------- -!> @brief convert 3x3x3x3 matrix into 9x9 matrix +!> @brief Convert 3x3x3x3 matrix into 9x9 matrix. !-------------------------------------------------------------------------------------------------- pure function math_3333to99(m3333) @@ -794,7 +766,7 @@ end function math_3333to99 !-------------------------------------------------------------------------------------------------- -!> @brief convert 9x9 matrix into 3x3x3x3 matrix +!> @brief Convert 9x9 matrix into 3x3x3x3 matrix. !-------------------------------------------------------------------------------------------------- pure function math_99to3333(m99) @@ -816,7 +788,7 @@ end function math_99to3333 !-------------------------------------------------------------------------------------------------- -!> @brief convert symmetric 3x3x3x3 matrix into 6x6 matrix +!> @brief Convert symmetric 3x3x3x3 matrix into 6x6 matrix. !> @details Weighted conversion (default) rearranges according to Nye and weights shear ! components according to Mandel. Advisable for matrix operations. ! Unweighted conversion only rearranges order according to Nye @@ -831,11 +803,7 @@ pure function math_sym3333to66(m3333,weighted) integer :: i,j - if (present(weighted)) then - w = merge(NRMMANDEL,1.0_pReal,weighted) - else - w = NRMMANDEL - end if + w = merge(NRMMANDEL,1.0_pReal,misc_optional(weighted,.true.)) #ifndef __INTEL_COMPILER do concurrent(i=1:6, j=1:6) @@ -849,7 +817,7 @@ end function math_sym3333to66 !-------------------------------------------------------------------------------------------------- -!> @brief convert 6x6 matrix into symmetric 3x3x3x3 matrix +!> @brief Convert 6x6 matrix into symmetric 3x3x3x3 matrix. !> @details Weighted conversion (default) rearranges according to Nye and weights shear ! components according to Mandel. Advisable for matrix operations. ! Unweighted conversion only rearranges order according to Nye @@ -864,11 +832,7 @@ pure function math_66toSym3333(m66,weighted) integer :: i,j - if (present(weighted)) then - w = merge(INVNRMMANDEL,1.0_pReal,weighted) - else - w = INVNRMMANDEL - end if + w = merge(INVNRMMANDEL,1.0_pReal,misc_optional(weighted,.true.)) do i=1,6; do j=1,6 math_66toSym3333(MAPNYE(1,i),MAPNYE(2,i),MAPNYE(1,j),MAPNYE(2,j)) = w(i)*w(j)*m66(i,j) @@ -996,30 +960,18 @@ impure elemental subroutine math_normal(x,mu,sigma) real(pReal), intent(out) :: x real(pReal), intent(in), optional :: mu, sigma - real(pReal) :: sigma_, mu_ real(pReal), dimension(2) :: rnd - if (present(mu)) then - mu_ = mu - else - mu_ = 0.0_pReal - end if - - if (present(sigma)) then - sigma_ = sigma - else - sigma_ = 1.0_pReal - end if - call random_number(rnd) - x = mu_ + sigma_ * sqrt(-2.0_pReal*log(1.0_pReal-rnd(1)))*cos(TAU*(1.0_pReal - rnd(2))) + x = misc_optional(mu,0.0_pReal) & + + misc_optional(sigma,1.0_pReal) * sqrt(-2.0_pReal*log(1.0_pReal-rnd(1)))*cos(TAU*(1.0_pReal - rnd(2))) end subroutine math_normal !-------------------------------------------------------------------------------------------------- -!> @brief eigenvalues and eigenvectors of symmetric matrix +!> @brief Calculate eigenvalues and eigenvectors of symmetric matrix. !-------------------------------------------------------------------------------------------------- pure subroutine math_eigh(w,v,error,m) @@ -1100,7 +1052,7 @@ end subroutine math_eigh33 !-------------------------------------------------------------------------------------------------- -!> @brief Calculate rotational part of a deformation gradient +!> @brief Calculate rotational part of a deformation gradient. !> @details https://www.jstor.org/stable/43637254 !! https://www.jstor.org/stable/43637372 !! https://doi.org/10.1023/A:1007407802076 @@ -1148,7 +1100,7 @@ end function math_rotationalPart !-------------------------------------------------------------------------------------------------- -!> @brief Eigenvalues of symmetric matrix +!> @brief Calculate eigenvalues of symmetric matrix. ! will return NaN on error !-------------------------------------------------------------------------------------------------- pure function math_eigvalsh(m) @@ -1161,8 +1113,8 @@ pure function math_eigvalsh(m) real(pReal), dimension(size(m,1)**2) :: work - m_= m ! copy matrix to input (will be destroyed) - call dsyev('N','U',size(m,1),m_,size(m,1),math_eigvalsh,work,size(work,1),ierr) + m_ = m ! m_ will be destroyed + call dsyev('N','U',size(m,1),m_,size(m,1),math_eigvalsh,work,size(work),ierr) if (ierr /= 0) math_eigvalsh = IEEE_value(1.0_pReal,IEEE_quiet_NaN) end function math_eigvalsh @@ -1416,7 +1368,7 @@ subroutine selfTest() do while(abs(math_det33(t33))<1.0e-9_pReal) call random_number(t33) end do - if (any(dNeq0(matmul(t33,math_inv33(t33)) - math_eye(3),tol=1.0e-9_pReal))) & + if (any(dNeq0(matmul(t33,math_inv33(t33)) - math_eye(3),tol=1.0e-8_pReal))) & error stop 'math_inv33' call math_invert33(t33_2,det,e,t33) diff --git a/src/mesh/DAMASK_mesh.f90 b/src/mesh/DAMASK_mesh.f90 index f10be4d0c..29014e49f 100644 --- a/src/mesh/DAMASK_mesh.f90 +++ b/src/mesh/DAMASK_mesh.f90 @@ -229,8 +229,9 @@ program DAMASK_mesh !-------------------------------------------------------------------------------------------------- ! doing initialization depending on active solvers - call FEM_Utilities_init + call FEM_Utilities_init() call FEM_mechanical_init(loadCases(1)%fieldBC(1)) + call config_numerics_deallocate() if (worldrank == 0) then open(newunit=statUnit,file=trim(getSolverJobName())//'.sta',form='FORMATTED',status='REPLACE') @@ -239,7 +240,7 @@ program DAMASK_mesh print'(/,1x,a)', '... writing initial configuration to file .................................' flush(IO_STDOUT) - call materialpoint_results(0,0.0_pReal) + call materialpoint_result(0,0.0_pReal) loadCaseLooping: do currentLoadCase = 1, size(loadCases) time0 = time ! load case start time @@ -324,8 +325,8 @@ program DAMASK_mesh if (mod(inc,loadCases(currentLoadCase)%outputFrequency) == 0) then ! at output frequency print'(/,1x,a)', '... writing results to file ...............................................' - call FEM_mechanical_updateCoords - call materialpoint_results(totalIncsCounter,time) + call FEM_mechanical_updateCoords() + call materialpoint_result(totalIncsCounter,time) end if diff --git a/src/mesh/FEM_quadrature.f90 b/src/mesh/FEM_quadrature.f90 index dde762eda..518cd1a4e 100644 --- a/src/mesh/FEM_quadrature.f90 +++ b/src/mesh/FEM_quadrature.f90 @@ -178,7 +178,7 @@ subroutine FEM_quadrature_init() permutationStar211([0.3523052600879940_pReal, 0.0992057202494530_pReal]), & permutationStar31([0.1344783347929940_pReal]) ] - call selfTest + call selfTest() end subroutine FEM_quadrature_init diff --git a/src/mesh/FEM_utilities.f90 b/src/mesh/FEM_utilities.f90 index 5307fcb85..6fc3b4f61 100644 --- a/src/mesh/FEM_utilities.f90 +++ b/src/mesh/FEM_utilities.f90 @@ -88,21 +88,17 @@ contains !ToDo: use functions in variable call !-------------------------------------------------------------------------------------------------- -!> @brief allocates all neccessary fields, sets debug flags +!> @brief Allocate all neccessary fields. !-------------------------------------------------------------------------------------------------- subroutine FEM_utilities_init character(len=pStringLen) :: petsc_optionsOrder type(tDict), pointer :: & - num_mesh, & - debug_mesh ! pointer to mesh debug options + num_mesh integer :: & p_s, & !< order of shape functions p_i !< integration order (quadrature rule) - character(len=*), parameter :: & - PETSCDEBUG = ' -snes_view -snes_monitor ' PetscErrorCode :: err_PETSc - logical :: debugPETSc !< use some in debug defined options for more verbose PETSc solution print'(/,1x,a)', '<<<+- FEM_utilities init -+>>>' @@ -117,17 +113,9 @@ subroutine FEM_utilities_init if (p_i < max(1,p_s-1) .or. p_i > p_s) & call IO_error(821,ext_msg='integration order (p_i) out of bounds') - debug_mesh => config_debug%get_dict('mesh',defaultVal=emptyDict) - debugPETSc = debug_mesh%contains('PETSc') - - if (debugPETSc) print'(3(/,1x,a),/)', & - 'Initializing PETSc with debug options: ', & - trim(PETScDebug), & - 'add more using the "PETSc_options" keyword in numerics.yaml' flush(IO_STDOUT) call PetscOptionsClear(PETSC_NULL_OPTIONS,err_PETSc) CHKERRQ(err_PETSc) - if (debugPETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(PETSCDEBUG),err_PETSc) CHKERRQ(err_PETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mechanical_snes_type newtonls & &-mechanical_snes_linesearch_type cp -mechanical_snes_ksp_ew & diff --git a/src/mesh/discretization_mesh.f90 b/src/mesh/discretization_mesh.f90 index abda549b7..b8505f3cb 100644 --- a/src/mesh/discretization_mesh.f90 +++ b/src/mesh/discretization_mesh.f90 @@ -20,7 +20,7 @@ module discretization_mesh use IO use config use discretization - use results + use result use FEM_quadrature use YAML_types use prec @@ -56,11 +56,10 @@ module discretization_mesh real(pReal), dimension(:,:,:), allocatable :: & mesh_ipCoordinates !< IP x,y,z coordinates (after deformation!) - external :: & #ifdef PETSC_USE_64BIT_INDICES - DMDestroy, & + external :: & + DMDestroy #endif - DMView ! ToDo: write interface public :: & discretization_mesh_init, & mesh_FEM_build_ipVolumes, & @@ -79,8 +78,7 @@ subroutine discretization_mesh_init(restart) PetscInt :: dimPlex, & mesh_Nnodes, & !< total number of nodes in mesh - j, & - debug_element, debug_ip + j PetscSF :: sf DM :: globalMesh PetscInt :: nFaceSets, Nboundaries, NelemsGlobal, Nelems @@ -104,11 +102,6 @@ subroutine discretization_mesh_init(restart) num_mesh => config_numerics%get_dict('mesh',defaultVal=emptyDict) p_i = num_mesh%get_asInt('p_i',defaultVal = 2) -!--------------------------------------------------------------------------------- -! read debug parameters - debug_element = config_debug%get_asInt('element',defaultVal=1) - debug_ip = config_debug%get_asInt('integrationpoint',defaultVal=1) - #if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>16) call DMPlexCreateFromFile(PETSC_COMM_WORLD,CLI_geomFile,'n/a',PETSC_TRUE,globalMesh,err_PETSc) #else @@ -120,8 +113,6 @@ subroutine discretization_mesh_init(restart) call DMGetStratumSize(globalMesh,'depth',dimPlex,NelemsGlobal,err_PETSc) CHKERRQ(err_PETSc) mesh_NcpElemsGlobal = int(NelemsGlobal) - call DMView(globalMesh, PETSC_VIEWER_STDOUT_WORLD,err_PETSc) - CHKERRQ(err_PETSc) ! get number of IDs in face sets (for boundary conditions?) call DMGetLabelSize(globalMesh,'Face Sets',Nboundaries,err_PETSc) @@ -185,9 +176,6 @@ subroutine discretization_mesh_init(restart) end do materialAt = materialAt + 1_pPETSCINT - if (debug_element < 1 .or. debug_element > mesh_NcpElems) call IO_error(602,ext_msg='element') - if (debug_ip < 1 .or. debug_ip > mesh_maxNips) call IO_error(602,ext_msg='IP') - allocate(mesh_node0(3,mesh_Nnodes),source=0.0_pReal) mesh_node0(1:dimPlex,:) = reshape(mesh_node0_temp,[dimPlex,mesh_Nnodes]) @@ -275,16 +263,16 @@ subroutine writeGeometry(coordinates_points,coordinates_nodes) coordinates_nodes, & coordinates_points - call results_openJobFile - call results_closeGroup(results_addGroup('geometry')) + call result_openJobFile() + call result_closeGroup(result_addGroup('geometry')) - call results_writeDataset(coordinates_nodes,'geometry','x_n', & - 'initial coordinates of the nodes','m') + call result_writeDataset(coordinates_nodes,'geometry','x_n', & + 'initial coordinates of the nodes','m') - call results_writeDataset(coordinates_points,'geometry','x_p', & - 'initial coordinates of the materialpoints (cell centers)','m') + call result_writeDataset(coordinates_points,'geometry','x_p', & + 'initial coordinates of the materialpoints (cell centers)','m') - call results_closeJobFile + call result_closeJobFile() end subroutine writeGeometry diff --git a/src/misc.f90 b/src/misc.f90 new file mode 100644 index 000000000..a56ea87c1 --- /dev/null +++ b/src/misc.f90 @@ -0,0 +1,183 @@ +!-------------------------------------------------------------------------------------------------- +!> @author Martin Diehl, KU Leuven +!> @author Philip Eisenlohr, Michigan State University +!> @brief Miscellaneous tools. +!-------------------------------------------------------------------------------------------------- +module misc + use prec + + implicit none(type,external) + private + + interface misc_optional + module procedure misc_optional_bool + module procedure misc_optional_integer + module procedure misc_optional_real + module procedure misc_optional_string + end interface misc_optional + + public :: & + misc_init, & + misc_optional + +contains + + +!-------------------------------------------------------------------------------------------------- +!> @brief Do self test. +!-------------------------------------------------------------------------------------------------- +subroutine misc_init() + + print'(/,1x,a)', '<<<+- misc init -+>>>' + + call misc_selfTest() + +end subroutine misc_init + + +!-------------------------------------------------------------------------------------------------- +!> @brief Return bool value if given, otherwise default. +!-------------------------------------------------------------------------------------------------- +pure function misc_optional_bool(given,default) result(var) + + logical, intent(in), optional :: given + logical, intent(in) :: default + logical :: var + + + if (present(given)) then + var = given + else + var = default + end if + +end function misc_optional_bool + + +!-------------------------------------------------------------------------------------------------- +!> @brief Return integer value if given, otherwise default. +!-------------------------------------------------------------------------------------------------- +pure function misc_optional_integer(given,default) result(var) + + integer, intent(in), optional :: given + integer, intent(in) :: default + integer :: var + + + if (present(given)) then + var = given + else + var = default + end if + +end function misc_optional_integer + + +!-------------------------------------------------------------------------------------------------- +!> @brief Return real value if given, otherwise default. +!-------------------------------------------------------------------------------------------------- +pure function misc_optional_real(given,default) result(var) + + real(pReal), intent(in), optional :: given + real(pReal), intent(in) :: default + real(pReal) :: var + + + if (present(given)) then + var = given + else + var = default + end if + +end function misc_optional_real + + +!-------------------------------------------------------------------------------------------------- +!> @brief Return string value if given, otherwise default. +!-------------------------------------------------------------------------------------------------- +pure function misc_optional_string(given,default) result(var) + + character(len=*), intent(in), optional :: given + character(len=*), intent(in) :: default + character(len=:), allocatable :: var + + + if (present(given)) then + var = given + else + var = default + end if + +end function misc_optional_string + + +!-------------------------------------------------------------------------------------------------- +!> @brief Check correctness of some misc functions. +!-------------------------------------------------------------------------------------------------- +subroutine misc_selfTest() + + real(pReal) :: r + + call random_number(r) + if (test_str('DAMASK') /= 'DAMASK') error stop 'optional_string, present' + if (test_str() /= 'default') error stop 'optional_string, not present' + if (misc_optional(default='default') /= 'default') error stop 'optional_string, default only' + if (test_int(20191102) /= 20191102) error stop 'optional_int, present' + if (test_int() /= 42) error stop 'optional_int, not present' + if (misc_optional(default=20191102) /= 20191102) error stop 'optional_int, default only' + if (dNeq(test_real(r),r)) error stop 'optional_float, present' + if (dNeq(test_real(),0.0_pReal)) error stop 'optional_float, not present' + if (dNeq(misc_optional(default=r),r)) error stop 'optional_float, default only' + if (test_bool(r<0.5_pReal) .neqv. r<0.5_pReal) error stop 'optional_bool, present' + if (.not. test_bool()) error stop 'optional_bool, not present' + if (misc_optional(default=r>0.5_pReal) .neqv. r>0.5_pReal) error stop 'optional_bool, default only' + +contains + + function test_str(str_in) result(str_out) + + character(len=:), allocatable :: str_out + character(len=*), intent(in), optional :: str_in + + + str_out = misc_optional_string(str_in,'default') + + end function test_str + + + function test_int(int_in) result(int_out) + + integer :: int_out + integer, intent(in), optional :: int_in + + + int_out = misc_optional_integer(int_in,42) + + end function test_int + + + function test_real(real_in) result(real_out) + + real(pReal) :: real_out + real(pReal), intent(in), optional :: real_in + + + real_out = misc_optional_real(real_in,0.0_pReal) + + end function test_real + + + function test_bool(bool_in) result(bool_out) + + logical :: bool_out + logical, intent(in), optional :: bool_in + + + bool_out = misc_optional_bool(bool_in,.true.) + + end function test_bool + + +end subroutine misc_selfTest + +end module misc diff --git a/src/parallelization.f90 b/src/parallelization.f90 index 04a852a15..6bca36c2a 100644 --- a/src/parallelization.f90 +++ b/src/parallelization.f90 @@ -46,6 +46,7 @@ end subroutine parallelization_bcast_str #else public :: & parallelization_init, & + parallelization_chkerr, & parallelization_bcast_str contains @@ -65,10 +66,12 @@ subroutine parallelization_init() PetscErrorCode :: err_PETSc #ifdef _OPENMP ! If openMP is enabled, check if the MPI libary supports it and initialize accordingly. - ! Otherwise, the first call to PETSc will do the initialization. call MPI_Init_Thread(MPI_THREAD_FUNNELED,threadLevel,err_MPI) if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI init failed' if (threadLevel @brief Check for MPI error. +!-------------------------------------------------------------------------------------------------- +subroutine parallelization_chkerr(e) + + integer(MPI_INTEGER_KIND), intent(in) :: e + + + if (e/=0_MPI_INTEGER_KIND) error stop 'MPI error' + +end subroutine parallelization_chkerr + + !-------------------------------------------------------------------------------------------------- !> @brief Broadcast a string from process 0. !-------------------------------------------------------------------------------------------------- diff --git a/src/phase.f90 b/src/phase.f90 index f7088b892..11795f3d6 100644 --- a/src/phase.f90 +++ b/src/phase.f90 @@ -13,7 +13,7 @@ module phase use IO use config use material - use results + use result use lattice use discretization use parallelization @@ -76,17 +76,6 @@ module phase type(tNumerics) :: num ! numerics parameters. Better name? - type :: tDebugOptions - logical :: & - basic, & - extensive, & - selective - integer :: & - element, & - ip, & - grain - end type tDebugOptions - type(tPlasticState), allocatable, dimension(:), public :: & plasticState type(tState), allocatable, dimension(:), public :: & @@ -108,20 +97,20 @@ module phase end subroutine thermal_init - module subroutine mechanical_results(group,ph) + module subroutine mechanical_result(group,ph) character(len=*), intent(in) :: group integer, intent(in) :: ph - end subroutine mechanical_results + end subroutine mechanical_result - module subroutine damage_results(group,ph) + module subroutine damage_result(group,ph) character(len=*), intent(in) :: group integer, intent(in) :: ph - end subroutine damage_results + end subroutine damage_result - module subroutine thermal_results(group,ph) + module subroutine thermal_result(group,ph) character(len=*), intent(in) :: group integer, intent(in) :: ph - end subroutine thermal_results + end subroutine thermal_result module subroutine mechanical_forward() end subroutine mechanical_forward @@ -196,6 +185,10 @@ module phase real(pReal), dimension(3,3) :: F_e end function mechanical_F_e + module function mechanical_F_i(ph,en) result(F_i) + integer, intent(in) :: ph,en + real(pReal), dimension(3,3) :: F_i + end function mechanical_F_i module function phase_F(co,ce) result(F) integer, intent(in) :: co, ce @@ -321,20 +314,19 @@ module phase end subroutine plastic_dependentState - module subroutine damage_anisobrittle_LiAndItsTangent(Ld, dLd_dTstar, S, ph,en) + module subroutine damage_anisobrittle_LiAndItsTangent(L_i, dL_i_dM_i, M_i, ph,en) integer, intent(in) :: ph, en real(pReal), intent(in), dimension(3,3) :: & - S + M_i real(pReal), intent(out), dimension(3,3) :: & - Ld !< damage velocity gradient + L_i !< damage velocity gradient real(pReal), intent(out), dimension(3,3,3,3) :: & - dLd_dTstar !< derivative of Ld with respect to Tstar (4th-order tensor) + dL_i_dM_i !< derivative of L_i with respect to M_i end subroutine damage_anisobrittle_LiAndItsTangent end interface - type(tDebugOptions) :: debugConstitutive #if __INTEL_COMPILER >= 1900 public :: & prec, & @@ -343,7 +335,7 @@ module phase IO, & config, & material, & - results, & + result, & lattice, & discretization, & HDF5_utilities @@ -358,7 +350,7 @@ module phase phase_K_T, & phase_mu_phi, & phase_mu_T, & - phase_results, & + phase_result, & phase_allocateState, & phase_forward, & phase_restore, & @@ -390,44 +382,36 @@ subroutine phase_init type(tDict), pointer :: & phases, & phase - type(tList), pointer :: & - debug_constitutive + character(len=:), allocatable :: refs print'(/,1x,a)', '<<<+- phase init -+>>>'; flush(IO_STDOUT) - debug_constitutive => config_debug%get_list('phase', defaultVal=emptyList) - debugConstitutive%basic = debug_constitutive%contains('basic') - debugConstitutive%extensive = debug_constitutive%contains('extensive') - debugConstitutive%selective = debug_constitutive%contains('selective') - debugConstitutive%element = config_debug%get_asInt('element', defaultVal = 1) - debugConstitutive%ip = config_debug%get_asInt('integrationpoint',defaultVal = 1) - debugConstitutive%grain = config_debug%get_asInt('constituent', defaultVal = 1) - - phases => config_material%get_dict('phase') - allocate(phase_lattice(phases%length)) allocate(phase_cOverA(phases%length),source=-1.0_pReal) allocate(phase_rho(phases%length)) allocate(phase_O_0(phases%length)) do ph = 1,phases%length + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) phase => phases%get_dict(ph) + refs = config_listReferences(phase,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs phase_lattice(ph) = phase%get_asString('lattice') if (all(phase_lattice(ph) /= ['cF','cI','hP','tI'])) & call IO_error(130,ext_msg='phase_init: '//phase%get_asString('lattice')) if (any(phase_lattice(ph) == ['hP','tI'])) & phase_cOverA(ph) = phase%get_asFloat('c/a') phase_rho(ph) = phase%get_asFloat('rho',defaultVal=0.0_pReal) - allocate(phase_O_0(ph)%data(count(material_phaseID==ph))) + allocate(phase_O_0(ph)%data(count(material_ID_phase==ph))) end do - do ce = 1, size(material_phaseID,2) + do ce = 1, size(material_ID_phase,2) ma = discretization_materialAt((ce-1)/discretization_nIPs+1) - do co = 1,homogenization_Nconstituents(material_homogenizationID(ce)) - ph = material_phaseID(co,ce) - phase_O_0(ph)%data(material_phaseEntry(co,ce)) = material_O_0(ma)%data(co) + do co = 1,homogenization_Nconstituents(material_ID_homogenization(ce)) + ph = material_ID_phase(co,ce) + phase_O_0(ph)%data(material_entry_phase(co,ce)) = material_O_0(ma)%data(co) end do end do @@ -437,7 +421,7 @@ subroutine phase_init end do call mechanical_init(phases) - call damage_init + call damage_init() call thermal_init(phases) call crystallite_init() @@ -513,30 +497,30 @@ end subroutine phase_forward !-------------------------------------------------------------------------------------------------- !> @brief writes constitutive results to HDF5 output file !-------------------------------------------------------------------------------------------------- -subroutine phase_results() +subroutine phase_result() integer :: ph character(len=:), allocatable :: group - call results_closeGroup(results_addGroup('/current/phase/')) + call result_closeGroup(result_addGroup('/current/phase/')) do ph = 1, size(material_name_phase) group = '/current/phase/'//trim(material_name_phase(ph))//'/' - call results_closeGroup(results_addGroup(group)) + call result_closeGroup(result_addGroup(group)) - call mechanical_results(group,ph) - call damage_results(group,ph) - call thermal_results(group,ph) + call mechanical_result(group,ph) + call damage_result(group,ph) + call thermal_result(group,ph) end do -end subroutine phase_results +end subroutine phase_result !-------------------------------------------------------------------------------------------------- -!> @brief allocates and initialize per grain variables +!> @brief Allocate and initialize. !-------------------------------------------------------------------------------------------------- subroutine crystallite_init() @@ -549,8 +533,8 @@ subroutine crystallite_init() type(tDict), pointer :: & num_crystallite, & phases - character(len=pStringLen) :: & - extmsg = '' + character(len=:), allocatable :: extmsg + num_crystallite => config_numerics%get_dict('crystallite',defaultVal=emptyDict) @@ -566,6 +550,7 @@ subroutine crystallite_init() num%nState = num_crystallite%get_asInt ('nState', defaultVal=20) num%nStress = num_crystallite%get_asInt ('nStress', defaultVal=40) + extmsg = '' if (num%subStepMinCryst <= 0.0_pReal) extmsg = trim(extmsg)//' subStepMinCryst' if (num%subStepSizeCryst <= 0.0_pReal) extmsg = trim(extmsg)//' subStepSizeCryst' if (num%stepIncreaseCryst <= 0.0_pReal) extmsg = trim(extmsg)//' stepIncreaseCryst' @@ -586,9 +571,9 @@ subroutine crystallite_init() do el = 1, discretization_Nelems do ip = 1, discretization_nIPs ce = (el-1)*discretization_nIPs + ip - do co = 1,homogenization_Nconstituents(material_homogenizationID(ce)) - en = material_phaseEntry(co,ce) - ph = material_phaseID(co,ce) + do co = 1,homogenization_Nconstituents(material_ID_homogenization(ce)) + en = material_entry_phase(co,ce) + ph = material_ID_phase(co,ce) call crystallite_orientations(co,ip,el) call plastic_dependentState(ph,en) ! update dependent state variables to be consistent with basic states end do @@ -613,13 +598,13 @@ subroutine crystallite_orientations(co,ip,el) integer :: ph, en - ph = material_phaseID(co,(el-1)*discretization_nIPs + ip) - en = material_phaseEntry(co,(el-1)*discretization_nIPs + ip) + ph = material_ID_phase(co,(el-1)*discretization_nIPs + ip) + en = material_entry_phase(co,(el-1)*discretization_nIPs + ip) call phase_O(ph)%data(en)%fromMatrix(transpose(math_rotationalPart(mechanical_F_e(ph,en)))) - if (plasticState(material_phaseID(1,(el-1)*discretization_nIPs + ip))%nonlocal) & - call plastic_nonlocal_updateCompatibility(phase_O,material_phaseID(1,(el-1)*discretization_nIPs + ip),ip,el) + if (plasticState(material_ID_phase(1,(el-1)*discretization_nIPs + ip))%nonlocal) & + call plastic_nonlocal_updateCompatibility(phase_O,material_ID_phase(1,(el-1)*discretization_nIPs + ip),ip,el) end subroutine crystallite_orientations @@ -640,8 +625,8 @@ function crystallite_push33ToRef(co,ce, tensor33) integer :: ph, en - ph = material_phaseID(co,ce) - en = material_phaseEntry(co,ce) + ph = material_ID_phase(co,ce) + en = material_entry_phase(co,ce) T = matmul(phase_O_0(ph)%data(en)%asMatrix(),transpose(math_inv33(phase_F(co,ce)))) ! ToDo: initial orientation correct? crystallite_push33ToRef = matmul(transpose(T),matmul(tensor33,T)) diff --git a/src/phase_damage.f90 b/src/phase_damage.f90 index ad592a846..df5e00575 100644 --- a/src/phase_damage.f90 +++ b/src/phase_damage.f90 @@ -49,22 +49,22 @@ submodule(phase) damage end subroutine isobrittle_deltaState - module subroutine anisobrittle_dotState(S, ph, en) + module subroutine anisobrittle_dotState(M_i, ph, en) integer, intent(in) :: ph,en real(pReal), intent(in), dimension(3,3) :: & - S + M_i end subroutine anisobrittle_dotState - module subroutine anisobrittle_results(phase,group) + module subroutine anisobrittle_result(phase,group) integer, intent(in) :: phase character(len=*), intent(in) :: group - end subroutine anisobrittle_results + end subroutine anisobrittle_result - module subroutine isobrittle_results(phase,group) + module subroutine isobrittle_result(phase,group) integer, intent(in) :: phase character(len=*), intent(in) :: group - end subroutine isobrittle_results + end subroutine isobrittle_result end interface @@ -79,15 +79,17 @@ module subroutine damage_init() ph, & Nmembers type(tDict), pointer :: & - phases, & - phase, & - source + phases, & + phase, & + source + character(len=:), allocatable :: refs logical:: damage_active + print'(/,1x,a)', '<<<+- phase:damage init -+>>>' - phases => config_material%get_dict('phase') + phases => config_material%get_dict('phase') allocate(current(phases%length)) allocate(damageState(phases%length)) allocate(param(phases%length)) @@ -95,13 +97,16 @@ module subroutine damage_init() damage_active = .false. do ph = 1,phases%length - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) allocate(current(ph)%phi(Nmembers),source=1.0_pReal) phase => phases%get_dict(ph) source => phase%get_dict('damage',defaultVal=emptyDict) if (source%length > 0) then + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(source,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs damage_active = .true. param(ph)%mu = source%get_asFloat('mu') param(ph)%l_c = source%get_asFloat('l_c') @@ -136,8 +141,8 @@ module function phase_damage_constitutive(Delta_t,co,ce) result(converged_) ph, en - ph = material_phaseID(co,ce) - en = material_phaseEntry(co,ce) + ph = material_ID_phase(co,ce) + en = material_entry_phase(co,ce) converged_ = .not. integrateDamageState(Delta_t,ph,en) @@ -175,10 +180,10 @@ module subroutine damage_restore(ce) co - do co = 1,homogenization_Nconstituents(material_homogenizationID(ce)) - if (damageState(material_phaseID(co,ce))%sizeState > 0) & - damageState(material_phaseID(co,ce))%state( :,material_phaseEntry(co,ce)) = & - damageState(material_phaseID(co,ce))%state0(:,material_phaseEntry(co,ce)) + do co = 1,homogenization_Nconstituents(material_ID_homogenization(ce)) + if (damageState(material_ID_phase(co,ce))%sizeState > 0) & + damageState(material_ID_phase(co,ce))%state( :,material_entry_phase(co,ce)) = & + damageState(material_ID_phase(co,ce))%state0(:,material_entry_phase(co,ce)) end do end subroutine damage_restore @@ -199,8 +204,8 @@ module function phase_f_phi(phi,co,ce) result(f) ph, & en - ph = material_phaseID(co,ce) - en = material_phaseEntry(co,ce) + ph = material_ID_phase(co,ce) + en = material_entry_phase(co,ce) select case(phase_damage(ph)) case(DAMAGE_ISOBRITTLE_ID,DAMAGE_ANISOBRITTLE_ID) @@ -339,26 +344,26 @@ end subroutine damage_restartRead !---------------------------------------------------------------------------------------------- !< @brief writes damage sources results to HDF5 output file !---------------------------------------------------------------------------------------------- -module subroutine damage_results(group,ph) +module subroutine damage_result(group,ph) character(len=*), intent(in) :: group integer, intent(in) :: ph if (phase_damage(ph) /= DAMAGE_UNDEFINED_ID) & - call results_closeGroup(results_addGroup(group//'damage')) + call result_closeGroup(result_addGroup(group//'damage')) sourceType: select case (phase_damage(ph)) case (DAMAGE_ISOBRITTLE_ID) sourceType - call isobrittle_results(ph,group//'damage/') + call isobrittle_result(ph,group//'damage/') case (DAMAGE_ANISOBRITTLE_ID) sourceType - call anisobrittle_results(ph,group//'damage/') + call anisobrittle_result(ph,group//'damage/') end select sourceType -end subroutine damage_results +end subroutine damage_result !-------------------------------------------------------------------------------------------------- @@ -379,7 +384,7 @@ function phase_damage_collectDotState(ph,en) result(broken) sourceType: select case (phase_damage(ph)) case (DAMAGE_ANISOBRITTLE_ID) sourceType - call anisobrittle_dotState(mechanical_S(ph,en), ph,en) ! correct stress? + call anisobrittle_dotState(mechanical_S(ph,en), ph,en) ! ToDo: use M_d end select sourceType @@ -399,7 +404,7 @@ module function phase_mu_phi(co,ce) result(mu) real(pReal) :: mu - mu = param(material_phaseID(co,ce))%mu + mu = param(material_ID_phase(co,ce))%mu end function phase_mu_phi @@ -413,7 +418,7 @@ module function phase_K_phi(co,ce) result(K) real(pReal), dimension(3,3) :: K - K = crystallite_push33ToRef(co,ce,param(material_phaseID(co,ce))%l_c**2*math_I3) + K = crystallite_push33ToRef(co,ce,param(material_ID_phase(co,ce))%l_c**2*math_I3) end function phase_K_phi @@ -471,8 +476,6 @@ function source_active(source_label) result(active_source) phases, & phase, & src - type(tList), pointer :: & - sources integer :: ph @@ -497,7 +500,7 @@ module subroutine phase_set_phi(phi,co,ce) integer, intent(in) :: ce, co - current(material_phaseID(co,ce))%phi(material_phaseEntry(co,ce)) = phi + current(material_ID_phase(co,ce))%phi(material_entry_phase(co,ce)) = phi end subroutine phase_set_phi diff --git a/src/phase_damage_anisobrittle.f90 b/src/phase_damage_anisobrittle.f90 index 072dbcb7f..69fa32564 100644 --- a/src/phase_damage_anisobrittle.f90 +++ b/src/phase_damage_anisobrittle.f90 @@ -8,8 +8,8 @@ submodule (phase:damage) anisobrittle type :: tParameters !< container type for internal constitutive parameters real(pReal) :: & - dot_o, & !< opening rate of cleavage planes - q !< damage rate sensitivity + dot_o_0, & !< opening rate of cleavage planes + p !< damage rate sensitivity real(pReal), dimension(:), allocatable :: & s_crit, & !< critical displacement g_crit !< critical load @@ -41,7 +41,9 @@ module function anisobrittle_init() result(mySources) src integer :: Nmembers,ph integer, dimension(:), allocatable :: N_cl - character(len=pStringLen) :: extmsg = '' + character(len=:), allocatable :: & + refs, & + extmsg mySources = source_active('anisobrittle') @@ -53,7 +55,7 @@ module function anisobrittle_init() result(mySources) phases => config_material%get_dict('phase') allocate(param(phases%length)) - + extmsg = '' do ph = 1, phases%length if (mySources(ph)) then @@ -62,11 +64,15 @@ module function anisobrittle_init() result(mySources) associate(prm => param(ph)) + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(src,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs + N_cl = src%get_as1dInt('N_cl',defaultVal=emptyIntArray) prm%sum_N_cl = sum(abs(N_cl)) - prm%q = src%get_asFloat('q') - prm%dot_o = src%get_asFloat('dot_o') + prm%p = src%get_asFloat('p') + prm%dot_o_0 = src%get_asFloat('dot_o_0') prm%s_crit = src%get_as1dFloat('s_crit', requiredSize=size(N_cl)) prm%g_crit = src%get_as1dFloat('g_crit', requiredSize=size(N_cl)) @@ -83,13 +89,13 @@ module function anisobrittle_init() result(mySources) prm%output = src%get_as1dString('output',defaultVal=emptyStringArray) #endif - ! sanity checks - if (prm%q <= 0.0_pReal) extmsg = trim(extmsg)//' q' - if (prm%dot_o <= 0.0_pReal) extmsg = trim(extmsg)//' dot_o' + ! sanity checks + if (prm%p <= 0.0_pReal) extmsg = trim(extmsg)//' p' + if (prm%dot_o_0 <= 0.0_pReal) extmsg = trim(extmsg)//' dot_o_0' if (any(prm%g_crit < 0.0_pReal)) extmsg = trim(extmsg)//' g_crit' if (any(prm%s_crit < 0.0_pReal)) extmsg = trim(extmsg)//' s_crit' - Nmembers = count(material_phaseID==ph) + Nmembers = count(material_ID_phase==ph) call phase_allocateState(damageState(ph),Nmembers,1,1,0) damageState(ph)%atol = src%get_asFloat('atol_phi',defaultVal=1.0e-9_pReal) if (any(damageState(ph)%atol < 0.0_pReal)) extmsg = trim(extmsg)//' atol_phi' @@ -107,33 +113,30 @@ end function anisobrittle_init !-------------------------------------------------------------------------------------------------- !> @brief !-------------------------------------------------------------------------------------------------- -module subroutine anisobrittle_dotState(S, ph,en) +module subroutine anisobrittle_dotState(M_i, ph,en) integer, intent(in) :: & ph,en real(pReal), intent(in), dimension(3,3) :: & - S + M_i integer :: & - i + a, i real(pReal) :: & - traction_d, traction_t, traction_n, traction_crit + traction, traction_crit associate(prm => param(ph)) damageState(ph)%dotState(1,en) = 0.0_pReal - do i = 1, prm%sum_N_cl - traction_d = math_tensordot(S,prm%cleavage_systems(1:3,1:3,1,i)) - traction_t = math_tensordot(S,prm%cleavage_systems(1:3,1:3,2,i)) - traction_n = math_tensordot(S,prm%cleavage_systems(1:3,1:3,3,i)) + do a = 1, prm%sum_N_cl + traction_crit = damage_phi(ph,en)**2 * prm%g_crit(a) + do i = 1,3 + traction = math_tensordot(M_i,prm%cleavage_systems(1:3,1:3,i,a)) - traction_crit = prm%g_crit(i)*damage_phi(ph,en)**2 - - damageState(ph)%dotState(1,en) = damageState(ph)%dotState(1,en) & - + prm%dot_o / prm%s_crit(i) & - * ((max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**prm%q + & - (max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**prm%q + & - (max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**prm%q) + damageState(ph)%dotState(1,en) = damageState(ph)%dotState(1,en) & + + prm%dot_o_0 / prm%s_crit(a) & + * (max(0.0_pReal, abs(traction) - traction_crit)/traction_crit)**prm%p + end do end do end associate @@ -141,9 +144,9 @@ end subroutine anisobrittle_dotState !-------------------------------------------------------------------------------------------------- -!> @brief writes results to HDF5 output file +!> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- -module subroutine anisobrittle_results(phase,group) +module subroutine anisobrittle_result(phase,group) integer, intent(in) :: phase character(len=*), intent(in) :: group @@ -154,72 +157,54 @@ module subroutine anisobrittle_results(phase,group) associate(prm => param(phase), stt => damageState(phase)%state) outputsLoop: do o = 1,size(prm%output) select case(trim(prm%output(o))) - case ('f_phi') - call results_writeDataset(stt,group,trim(prm%output(o)),'driving force','-') + case ('Psi_D') + call result_writeDataset(stt,group,trim(prm%output(o)),'damage energy density','J/m³') end select end do outputsLoop end associate -end subroutine anisobrittle_results +end subroutine anisobrittle_result !-------------------------------------------------------------------------------------------------- !> @brief contains the constitutive equation for calculating the velocity gradient !-------------------------------------------------------------------------------------------------- -module subroutine damage_anisobrittle_LiAndItsTangent(Ld, dLd_dTstar, S, ph,en) +module subroutine damage_anisobrittle_LiAndItsTangent(L_i, dL_i_dM_i, M_i, ph,en) integer, intent(in) :: & ph,en real(pReal), intent(in), dimension(3,3) :: & - S + M_i real(pReal), intent(out), dimension(3,3) :: & - Ld !< damage velocity gradient + L_i !< damage velocity gradient real(pReal), intent(out), dimension(3,3,3,3) :: & - dLd_dTstar !< derivative of Ld with respect to Tstar (4th-order tensor) + dL_i_dM_i !< derivative of L_i with respect to M_i integer :: & - i, k, l, m, n + a, k, l, m, n, i real(pReal) :: & - traction_d, traction_t, traction_n, traction_crit, & - udotd, dudotd_dt, udott, dudott_dt, udotn, dudotn_dt + traction, traction_crit, & + udot, dudot_dt - Ld = 0.0_pReal - dLd_dTstar = 0.0_pReal + L_i = 0.0_pReal + dL_i_dM_i = 0.0_pReal associate(prm => param(ph)) - do i = 1,prm%sum_N_cl - traction_crit = prm%g_crit(i)*damage_phi(ph,en)**2 + do a = 1,prm%sum_N_cl + traction_crit = damage_phi(ph,en)**2 * prm%g_crit(a) - traction_d = math_tensordot(S,prm%cleavage_systems(1:3,1:3,1,i)) - if (abs(traction_d) > traction_crit + tol_math_check) then - udotd = sign(1.0_pReal,traction_d)* prm%dot_o * ((abs(traction_d) - traction_crit)/traction_crit)**prm%q - Ld = Ld + udotd*prm%cleavage_systems(1:3,1:3,1,i) - dudotd_dt = sign(1.0_pReal,traction_d)*udotd*prm%q / (abs(traction_d) - traction_crit) - forall (k=1:3,l=1:3,m=1:3,n=1:3) & - dLd_dTstar(k,l,m,n) = dLd_dTstar(k,l,m,n) & - + dudotd_dt*prm%cleavage_systems(k,l,1,i) * prm%cleavage_systems(m,n,1,i) - end if - - traction_t = math_tensordot(S,prm%cleavage_systems(1:3,1:3,2,i)) - if (abs(traction_t) > traction_crit + tol_math_check) then - udott = sign(1.0_pReal,traction_t)* prm%dot_o * ((abs(traction_t) - traction_crit)/traction_crit)**prm%q - Ld = Ld + udott*prm%cleavage_systems(1:3,1:3,2,i) - dudott_dt = sign(1.0_pReal,traction_t)*udott*prm%q / (abs(traction_t) - traction_crit) - forall (k=1:3,l=1:3,m=1:3,n=1:3) & - dLd_dTstar(k,l,m,n) = dLd_dTstar(k,l,m,n) & - + dudott_dt*prm%cleavage_systems(k,l,2,i) * prm%cleavage_systems(m,n,2,i) - end if - - traction_n = math_tensordot(S,prm%cleavage_systems(1:3,1:3,3,i)) - if (abs(traction_n) > traction_crit + tol_math_check) then - udotn = sign(1.0_pReal,traction_n)* prm%dot_o * ((abs(traction_n) - traction_crit)/traction_crit)**prm%q - Ld = Ld + udotn*prm%cleavage_systems(1:3,1:3,3,i) - dudotn_dt = sign(1.0_pReal,traction_n)*udotn*prm%q / (abs(traction_n) - traction_crit) - forall (k=1:3,l=1:3,m=1:3,n=1:3) & - dLd_dTstar(k,l,m,n) = dLd_dTstar(k,l,m,n) & - + dudotn_dt*prm%cleavage_systems(k,l,3,i) * prm%cleavage_systems(m,n,3,i) - end if - end do + do i = 1, 3 + traction = math_tensordot(M_i,prm%cleavage_systems(1:3,1:3,i,a)) + if (abs(traction) > traction_crit + tol_math_check) then + udot = sign(1.0_pReal,traction)* prm%dot_o_0 * ((abs(traction) - traction_crit)/traction_crit)**prm%p + L_i = L_i + udot*prm%cleavage_systems(1:3,1:3,i,a) + dudot_dt = sign(1.0_pReal,traction)*udot*prm%p / (abs(traction) - traction_crit) + forall (k=1:3,l=1:3,m=1:3,n=1:3) & + dL_i_dM_i(k,l,m,n) = dL_i_dM_i(k,l,m,n) & + + dudot_dt*prm%cleavage_systems(k,l,i,a) * prm%cleavage_systems(m,n,i,a) + end if + end do + end do end associate end subroutine damage_anisobrittle_LiAndItsTangent diff --git a/src/phase_damage_isobrittle.f90 b/src/phase_damage_isobrittle.f90 index 0e00974e3..62a2eb7ec 100644 --- a/src/phase_damage_isobrittle.f90 +++ b/src/phase_damage_isobrittle.f90 @@ -39,7 +39,9 @@ module function isobrittle_init() result(mySources) phase, & src integer :: Nmembers,ph - character(len=pStringLen) :: extmsg = '' + character(len=:), allocatable :: & + refs, & + extmsg mySources = source_active('isobrittle') @@ -53,6 +55,7 @@ module function isobrittle_init() result(mySources) allocate(param(phases%length)) allocate(state(phases%length)) allocate(deltaState(phases%length)) + extmsg = '' do ph = 1, phases%length if (mySources(ph)) then @@ -63,6 +66,10 @@ module function isobrittle_init() result(mySources) prm%W_crit = src%get_asFloat('G_crit')/src%get_asFloat('l_c') + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(src,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs + #if defined (__GFORTRAN__) prm%output = output_as1dString(src) #else @@ -72,7 +79,7 @@ module function isobrittle_init() result(mySources) ! sanity checks if (prm%W_crit <= 0.0_pReal) extmsg = trim(extmsg)//' W_crit' - Nmembers = count(material_phaseID==ph) + Nmembers = count(material_ID_phase==ph) call phase_allocateState(damageState(ph),Nmembers,1,0,1) damageState(ph)%atol = src%get_asFloat('atol_phi',defaultVal=1.0e-9_pReal) if (any(damageState(ph)%atol < 0.0_pReal)) extmsg = trim(extmsg)//' atol_phi' @@ -113,7 +120,7 @@ module subroutine isobrittle_deltaState(C, Fe, ph,en) associate(prm => param(ph), stt => state(ph), dlt => deltaState(ph)) - r_W = (2.0_pReal*dot_product(epsilon,matmul(C,epsilon)))/prm%W_crit + r_W = (0.5_pReal*dot_product(epsilon,matmul(C,epsilon)))/prm%W_crit dlt%r_W(en) = merge(r_W - stt%r_W(en), 0.0_pReal, r_W > stt%r_W(en)) end associate @@ -124,7 +131,7 @@ end subroutine isobrittle_deltaState !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- -module subroutine isobrittle_results(phase,group) +module subroutine isobrittle_result(phase,group) integer, intent(in) :: phase character(len=*), intent(in) :: group @@ -136,13 +143,13 @@ module subroutine isobrittle_results(phase,group) outputsLoop: do o = 1,size(prm%output) select case(trim(prm%output(o))) - case ('f_phi') - call results_writeDataset(stt,group,trim(prm%output(o)),'driving force','-') + case ('r_W') + call result_writeDataset(stt,group,trim(prm%output(o)),'ratio between actual and critical strain energy density','-') end select end do outputsLoop end associate -end subroutine isobrittle_results +end subroutine isobrittle_result end submodule isobrittle diff --git a/src/phase_mechanical.f90 b/src/phase_mechanical.f90 index 9229abe23..4049914de 100644 --- a/src/phase_mechanical.f90 +++ b/src/phase_mechanical.f90 @@ -129,35 +129,35 @@ submodule(phase) mechanical end subroutine plastic_LpAndItsTangents - module subroutine plastic_isotropic_results(ph,group) + module subroutine plastic_isotropic_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group - end subroutine plastic_isotropic_results + end subroutine plastic_isotropic_result - module subroutine plastic_phenopowerlaw_results(ph,group) + module subroutine plastic_phenopowerlaw_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group - end subroutine plastic_phenopowerlaw_results + end subroutine plastic_phenopowerlaw_result - module subroutine plastic_kinehardening_results(ph,group) + module subroutine plastic_kinehardening_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group - end subroutine plastic_kinehardening_results + end subroutine plastic_kinehardening_result - module subroutine plastic_dislotwin_results(ph,group) + module subroutine plastic_dislotwin_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group - end subroutine plastic_dislotwin_results + end subroutine plastic_dislotwin_result - module subroutine plastic_dislotungsten_results(ph,group) + module subroutine plastic_dislotungsten_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group - end subroutine plastic_dislotungsten_results + end subroutine plastic_dislotungsten_result - module subroutine plastic_nonlocal_results(ph,group) + module subroutine plastic_nonlocal_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group - end subroutine plastic_nonlocal_results + end subroutine plastic_nonlocal_result module function plastic_dislotwin_homogenizedC(ph,en) result(homogenizedC) real(pReal), dimension(6,6) :: homogenizedC @@ -215,6 +215,7 @@ module subroutine mechanical_init(phases) phase, & mech + print'(/,1x,a)', '<<<+- phase:mechanical init -+>>>' !------------------------------------------------------------------------------------------------- @@ -236,7 +237,7 @@ module subroutine mechanical_init(phases) allocate(phase_mechanical_S0(phases%length)) do ph = 1, phases%length - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) allocate(phase_mechanical_Fe(ph)%data(3,3,Nmembers)) allocate(phase_mechanical_Fi(ph)%data(3,3,Nmembers)) @@ -259,11 +260,11 @@ module subroutine mechanical_init(phases) #endif end do - do ce = 1, size(material_phaseID,2) + do ce = 1, size(material_ID_phase,2) ma = discretization_materialAt((ce-1)/discretization_nIPs+1) - do co = 1,homogenization_Nconstituents(material_homogenizationID(ce)) - ph = material_phaseID(co,ce) - en = material_phaseEntry(co,ce) + do co = 1,homogenization_Nconstituents(material_ID_homogenization(ce)) + ph = material_ID_phase(co,ce) + en = material_entry_phase(co,ce) phase_mechanical_F(ph)%data(1:3,1:3,en) = math_I3 phase_mechanical_Fp(ph)%data(1:3,1:3,en) = material_O_0(ma)%data(co)%asMatrix() ! Fp reflects initial orientation (see 10.1016/j.actamat.2006.01.005) phase_mechanical_Fe(ph)%data(1:3,1:3,en) = matmul(material_V_e_0(ma)%data(1:3,1:3,co), & @@ -318,7 +319,7 @@ module subroutine mechanical_init(phases) end subroutine mechanical_init -module subroutine mechanical_results(group,ph) +module subroutine mechanical_result(group,ph) character(len=*), intent(in) :: group integer, intent(in) :: ph @@ -329,27 +330,27 @@ module subroutine mechanical_results(group,ph) select case(phase_plasticity(ph)) case(PLASTIC_ISOTROPIC_ID) - call plastic_isotropic_results(ph,group//'mechanical/') + call plastic_isotropic_result(ph,group//'mechanical/') case(PLASTIC_PHENOPOWERLAW_ID) - call plastic_phenopowerlaw_results(ph,group//'mechanical/') + call plastic_phenopowerlaw_result(ph,group//'mechanical/') case(PLASTIC_KINEHARDENING_ID) - call plastic_kinehardening_results(ph,group//'mechanical/') + call plastic_kinehardening_result(ph,group//'mechanical/') case(PLASTIC_DISLOTWIN_ID) - call plastic_dislotwin_results(ph,group//'mechanical/') + call plastic_dislotwin_result(ph,group//'mechanical/') case(PLASTIC_DISLOTUNGSTEN_ID) - call plastic_dislotungsten_results(ph,group//'mechanical/') + call plastic_dislotungsten_result(ph,group//'mechanical/') case(PLASTIC_NONLOCAL_ID) - call plastic_nonlocal_results(ph,group//'mechanical/') + call plastic_nonlocal_result(ph,group//'mechanical/') end select -end subroutine mechanical_results +end subroutine mechanical_result !-------------------------------------------------------------------------------------------------- @@ -415,8 +416,8 @@ function integrateStress(F,subFp0,subFi0,Delta_t,ph,en) result(broken) broken = .true. call plastic_dependentState(ph,en) - Lpguess = phase_mechanical_Lp(ph)%data(1:3,1:3,en) ! take as first guess - Liguess = phase_mechanical_Li(ph)%data(1:3,1:3,en) ! take as first guess + Lpguess = phase_mechanical_Lp(ph)%data(1:3,1:3,en) ! take as first guess + Liguess = phase_mechanical_Li(ph)%data(1:3,1:3,en) ! take as first guess call math_invert33(invFp_current,error=error,A=subFp0) if (error) return ! error @@ -897,41 +898,41 @@ subroutine results(group,ph) integer :: ou - call results_closeGroup(results_addGroup(group//'/mechanical')) + call result_closeGroup(result_addGroup(group//'/mechanical')) do ou = 1, size(output_mechanical(ph)%label) select case (output_mechanical(ph)%label(ou)) case('F') - call results_writeDataset(phase_mechanical_F(ph)%data,group//'/mechanical/','F',& + call result_writeDataset(phase_mechanical_F(ph)%data,group//'/mechanical/','F',& 'deformation gradient','1') case('F_e') - call results_writeDataset(phase_mechanical_Fe(ph)%data,group//'/mechanical/','F_e',& + call result_writeDataset(phase_mechanical_Fe(ph)%data,group//'/mechanical/','F_e',& 'elastic deformation gradient','1') case('F_p') - call results_writeDataset(phase_mechanical_Fp(ph)%data,group//'/mechanical/','F_p', & + call result_writeDataset(phase_mechanical_Fp(ph)%data,group//'/mechanical/','F_p', & 'plastic deformation gradient','1') case('F_i') - call results_writeDataset(phase_mechanical_Fi(ph)%data,group//'/mechanical/','F_i', & + call result_writeDataset(phase_mechanical_Fi(ph)%data,group//'/mechanical/','F_i', & 'inelastic deformation gradient','1') case('L_p') - call results_writeDataset(phase_mechanical_Lp(ph)%data,group//'/mechanical/','L_p', & + call result_writeDataset(phase_mechanical_Lp(ph)%data,group//'/mechanical/','L_p', & 'plastic velocity gradient','1/s') case('L_i') - call results_writeDataset(phase_mechanical_Li(ph)%data,group//'/mechanical/','L_i', & + call result_writeDataset(phase_mechanical_Li(ph)%data,group//'/mechanical/','L_i', & 'inelastic velocity gradient','1/s') case('P') - call results_writeDataset(phase_mechanical_P(ph)%data,group//'/mechanical/','P', & + call result_writeDataset(phase_mechanical_P(ph)%data,group//'/mechanical/','P', & 'first Piola-Kirchhoff stress','Pa') case('S') - call results_writeDataset(phase_mechanical_S(ph)%data,group//'/mechanical/','S', & + call result_writeDataset(phase_mechanical_S(ph)%data,group//'/mechanical/','S', & 'second Piola-Kirchhoff stress','Pa') case('O') - call results_writeDataset(to_quaternion(phase_O(ph)%data),group//'/mechanical','O', & + call result_writeDataset(to_quaternion(phase_O(ph)%data),group//'/mechanical','O', & 'crystal orientation as quaternion q_0 (q_1 q_2 q_3)','1') - call results_addAttribute('lattice',phase_lattice(ph),group//'/mechanical/O') + call result_addAttribute('lattice',phase_lattice(ph),group//'/mechanical/O') if (any(phase_lattice(ph) == ['hP', 'tI'])) & - call results_addAttribute('c/a',phase_cOverA(ph),group//'/mechanical/O') + call result_addAttribute('c/a',phase_cOverA(ph),group//'/mechanical/O') end select end do @@ -1004,11 +1005,11 @@ module function phase_mechanical_constitutive(Delta_t,co,ce) result(converged_) subLi0, & subF0, & subF - real(pReal), dimension(plasticState(material_phaseID(co,ce))%sizeState) :: subState0 + real(pReal), dimension(plasticState(material_ID_phase(co,ce))%sizeState) :: subState0 - ph = material_phaseID(co,ce) - en = material_phaseEntry(co,ce) + ph = material_ID_phase(co,ce) + en = material_entry_phase(co,ce) subState0 = plasticState(ph)%state0(:,en) subLi0 = phase_mechanical_Li0(ph)%data(1:3,1:3,en) @@ -1081,9 +1082,9 @@ module subroutine mechanical_restore(ce,includeL) co, ph, en - do co = 1,homogenization_Nconstituents(material_homogenizationID(ce)) - ph = material_phaseID(co,ce) - en = material_phaseEntry(co,ce) + do co = 1,homogenization_Nconstituents(material_ID_homogenization(ce)) + ph = material_ID_phase(co,ce) + en = material_entry_phase(co,ce) if (includeL) then phase_mechanical_Lp(ph)%data(1:3,1:3,en) = phase_mechanical_Lp0(ph)%data(1:3,1:3,en) phase_mechanical_Li(ph)%data(1:3,1:3,en) = phase_mechanical_Li0(ph)%data(1:3,1:3,en) @@ -1132,8 +1133,8 @@ module function phase_mechanical_dPdF(Delta_t,co,ce) result(dPdF) logical :: error - ph = material_phaseID(co,ce) - en = material_phaseEntry(co,ce) + ph = material_ID_phase(co,ce) + en = material_entry_phase(co,ce) call phase_hooke_SandItsTangents(devNull,dSdFe,dSdFi, & phase_mechanical_Fe(ph)%data(1:3,1:3,en), & @@ -1318,6 +1319,20 @@ module function mechanical_F_e(ph,en) result(F_e) end function mechanical_F_e +!-------------------------------------------------------------------------------------------------- +!< @brief Get eigen deformation gradient (for use by non-mech physics). +!-------------------------------------------------------------------------------------------------- +module function mechanical_F_i(ph,en) result(F_i) + + integer, intent(in) :: ph,en + real(pReal), dimension(3,3) :: F_i + + + F_i = phase_mechanical_Fi(ph)%data(1:3,1:3,en) + +end function mechanical_F_i + + !-------------------------------------------------------------------------------------------------- !< @brief Get second Piola-Kirchhoff stress (for use by homogenization). !-------------------------------------------------------------------------------------------------- @@ -1327,7 +1342,7 @@ module function phase_P(co,ce) result(P) real(pReal), dimension(3,3) :: P - P = phase_mechanical_P(material_phaseID(co,ce))%data(1:3,1:3,material_phaseEntry(co,ce)) + P = phase_mechanical_P(material_ID_phase(co,ce))%data(1:3,1:3,material_entry_phase(co,ce)) end function phase_P @@ -1341,7 +1356,7 @@ module function phase_F(co,ce) result(F) real(pReal), dimension(3,3) :: F - F = phase_mechanical_F(material_phaseID(co,ce))%data(1:3,1:3,material_phaseEntry(co,ce)) + F = phase_mechanical_F(material_ID_phase(co,ce))%data(1:3,1:3,material_entry_phase(co,ce)) end function phase_F @@ -1355,7 +1370,7 @@ module subroutine phase_set_F(F,co,ce) integer, intent(in) :: co, ce - phase_mechanical_F(material_phaseID(co,ce))%data(1:3,1:3,material_phaseEntry(co,ce)) = F + phase_mechanical_F(material_ID_phase(co,ce))%data(1:3,1:3,material_entry_phase(co,ce)) = F end subroutine phase_set_F diff --git a/src/phase_mechanical_eigen.f90 b/src/phase_mechanical_eigen.f90 index 1e639b051..6b7a079b0 100644 --- a/src/phase_mechanical_eigen.f90 +++ b/src/phase_mechanical_eigen.f90 @@ -45,8 +45,10 @@ module subroutine eigen_init(phases) type(tList), pointer :: & kinematics + print'(/,1x,a)', '<<<+- phase:mechanical:eigen init -+>>>' + !-------------------------------------------------------------------------------------------------- ! explicit eigen mechanisms allocate(Nmodels(phases%length),source = 0) @@ -119,8 +121,6 @@ function kinematics_active2(kinematics_label) result(active_kinematics) phases, & phase, & kinematics_type - type(tList), pointer :: & - kinematics integer :: ph diff --git a/src/phase_mechanical_eigen_thermalexpansion.f90 b/src/phase_mechanical_eigen_thermalexpansion.f90 index ddd495687..23c6b0aee 100644 --- a/src/phase_mechanical_eigen_thermalexpansion.f90 +++ b/src/phase_mechanical_eigen_thermalexpansion.f90 @@ -36,13 +36,14 @@ module function thermalexpansion_init(kinematics_length) result(myKinematics) mech - print'(/,1x,a)', '<<<+- phase:mechanical:eigen:thermalexpansion init -+>>>' - myKinematics = kinematics_active('thermalexpansion',kinematics_length) Ninstances = count(myKinematics) print'(/,a,i2)', ' # phases: ',Ninstances; flush(IO_STDOUT) if (Ninstances == 0) return + print'(/,1x,a)', '<<<+- phase:mechanical:eigen:thermalexpansion init -+>>>' + + phases => config_material%get_dict('phase') allocate(param(Ninstances)) allocate(kinematics_thermal_expansion_instance(phases%length), source=0) diff --git a/src/phase_mechanical_elastic.f90 b/src/phase_mechanical_elastic.f90 index e5cc417aa..15a5d29c2 100644 --- a/src/phase_mechanical_elastic.f90 +++ b/src/phase_mechanical_elastic.f90 @@ -28,6 +28,7 @@ module subroutine elastic_init(phases) phase, & mech, & elastic + character(len=:), allocatable :: refs print'(/,1x,a)', '<<<+- phase:mechanical:elastic init -+>>>' @@ -35,12 +36,16 @@ module subroutine elastic_init(phases) print'(/,a,i0)', ' # phases: ',phases%length; flush(IO_STDOUT) + allocate(param(phases%length)) do ph = 1, phases%length phase => phases%get_dict(ph) mech => phase%get_dict('mechanical') elastic => mech%get_dict('elastic') + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(elastic,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs if (elastic%get_asString('type') /= 'Hooke') call IO_error(200,ext_msg=elastic%get_asString('type')) associate(prm => param(ph)) diff --git a/src/phase_mechanical_plastic.f90 b/src/phase_mechanical_plastic.f90 index bff25895c..4140e0805 100644 --- a/src/phase_mechanical_plastic.f90 +++ b/src/phase_mechanical_plastic.f90 @@ -226,7 +226,7 @@ module subroutine plastic_init end subroutine plastic_init !-------------------------------------------------------------------------------------------------- -!> @brief contains the constitutive equation for calculating the velocity gradient +!> @brief constitutive equation for calculating the velocity gradient ! ToDo: Discuss whether it makes sense if crystallite handles the configuration conversion, i.e. ! Mp in, dLp_dMp out !-------------------------------------------------------------------------------------------------- @@ -366,7 +366,7 @@ end subroutine plastic_dependentState !-------------------------------------------------------------------------------------------------- -!> @brief for constitutive models having an instantaneous change of state +!> @brief for constitutive models that have an instantaneous change of state !> will return false if delta state is not needed/supported by the constitutive model !-------------------------------------------------------------------------------------------------- module function plastic_deltaState(ph, en) result(broken) diff --git a/src/phase_mechanical_plastic_dislotungsten.f90 b/src/phase_mechanical_plastic_dislotungsten.f90 index c363b32d5..e37511967 100644 --- a/src/phase_mechanical_plastic_dislotungsten.f90 +++ b/src/phase_mechanical_plastic_dislotungsten.f90 @@ -93,8 +93,9 @@ module function plastic_dislotungsten_init() result(myPlasticity) rho_mob_0, & !< initial dislocation density rho_dip_0, & !< initial dipole density a !< non-Schmid coefficients - character(len=pStringLen) :: & - extmsg = '' + character(len=:), allocatable :: & + refs, & + extmsg type(tDict), pointer :: & phases, & phase, & @@ -111,11 +112,13 @@ module function plastic_dislotungsten_init() result(myPlasticity) print'(/,1x,a)', 'D. Cereceda et al., International Journal of Plasticity 78:242–256, 2016' print'( 1x,a)', 'https://doi.org/10.1016/j.ijplas.2015.09.002' + phases => config_material%get_dict('phase') allocate(param(phases%length)) allocate(indexDotState(phases%length)) allocate(state(phases%length)) allocate(dependentState(phases%length)) + extmsg = '' do ph = 1, phases%length if (.not. myPlasticity(ph)) cycle @@ -127,6 +130,10 @@ module function plastic_dislotungsten_init() result(myPlasticity) mech => phase%get_dict('mechanical') pl => mech%get_dict('plastic') + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(pl,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs + #if defined (__GFORTRAN__) prm%output = output_as1dString(pl) #else @@ -218,7 +225,7 @@ module function plastic_dislotungsten_init() result(myPlasticity) !-------------------------------------------------------------------------------------------------- ! allocate state arrays - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) sizeDotState = size(['rho_mob ','rho_dip ','gamma_sl']) * prm%sum_N_sl sizeState = sizeDotState @@ -403,7 +410,7 @@ end subroutine dislotungsten_dependentState !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- -module subroutine plastic_dislotungsten_results(ph,group) +module subroutine plastic_dislotungsten_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group @@ -418,35 +425,35 @@ module subroutine plastic_dislotungsten_results(ph,group) select case(trim(prm%output(ou))) case('rho_mob') - call results_writeDataset(stt%rho_mob,group,trim(prm%output(ou)), & - 'mobile dislocation density','1/m²',prm%systems_sl) + call result_writeDataset(stt%rho_mob,group,trim(prm%output(ou)), & + 'mobile dislocation density','1/m²',prm%systems_sl) case('rho_dip') - call results_writeDataset(stt%rho_dip,group,trim(prm%output(ou)), & - 'dislocation dipole density','1/m²',prm%systems_sl) + call result_writeDataset(stt%rho_dip,group,trim(prm%output(ou)), & + 'dislocation dipole density','1/m²',prm%systems_sl) case('gamma_sl') - call results_writeDataset(stt%gamma_sl,group,trim(prm%output(ou)), & - 'plastic shear','1',prm%systems_sl) + call result_writeDataset(stt%gamma_sl,group,trim(prm%output(ou)), & + 'plastic shear','1',prm%systems_sl) case('Lambda_sl') - call results_writeDataset(dst%Lambda_sl,group,trim(prm%output(ou)), & - 'mean free path for slip','m',prm%systems_sl) + call result_writeDataset(dst%Lambda_sl,group,trim(prm%output(ou)), & + 'mean free path for slip','m',prm%systems_sl) case('tau_pass') - call results_writeDataset(dst%tau_pass,group,trim(prm%output(ou)), & - 'threshold stress for slip','Pa',prm%systems_sl) + call result_writeDataset(dst%tau_pass,group,trim(prm%output(ou)), & + 'threshold stress for slip','Pa',prm%systems_sl) end select end do end associate -end subroutine plastic_dislotungsten_results +end subroutine plastic_dislotungsten_result !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on slip systems, their derivatives with respect to resolved ! stress, and the resolved stress. !> @details Derivatives and resolved stress are calculated only optionally. -! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to -! have the optional arguments at the end +! NOTE: Contrary to common convention, here the result (i.e. intent(out)) variables have to be put +! at the end since some of them are optional. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics(Mp,T,ph,en, & dot_gamma_pos,dot_gamma_neg,ddot_gamma_dtau_pos,ddot_gamma_dtau_neg,tau_pos_out,tau_neg_out) diff --git a/src/phase_mechanical_plastic_dislotwin.f90 b/src/phase_mechanical_plastic_dislotwin.f90 index ab3aa65e0..ee6ccb9d1 100644 --- a/src/phase_mechanical_plastic_dislotwin.f90 +++ b/src/phase_mechanical_plastic_dislotwin.f90 @@ -64,9 +64,9 @@ submodule(phase:plastic) dislotwin P_tw, & P_tr integer :: & - sum_N_sl, & !< total number of active slip system - sum_N_tw, & !< total number of active twin system - sum_N_tr !< total number of active transformation system + sum_N_sl, & !< total number of active slip systems + sum_N_tw, & !< total number of active twin systems + sum_N_tr !< total number of active transformation systems integer, allocatable, dimension(:) :: & N_tw, & N_tr @@ -140,8 +140,9 @@ module function plastic_dislotwin_init() result(myPlasticity) real(pReal), allocatable, dimension(:) :: & rho_mob_0, & !< initial unipolar dislocation density per slip system rho_dip_0 !< initial dipole dislocation density per slip system - character(len=pStringLen) :: & - extmsg = '' + character(len=:), allocatable :: & + refs, & + extmsg type(tDict), pointer :: & phases, & phase, & @@ -170,6 +171,7 @@ module function plastic_dislotwin_init() result(myPlasticity) allocate(indexDotState(phases%length)) allocate(state(phases%length)) allocate(dependentState(phases%length)) + extmsg = '' do ph = 1, phases%length if (.not. myPlasticity(ph)) cycle @@ -181,6 +183,10 @@ module function plastic_dislotwin_init() result(myPlasticity) mech => phase%get_dict('mechanical') pl => mech%get_dict('plastic') + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(pl,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs + #if defined (__GFORTRAN__) prm%output = output_as1dString(pl) #else @@ -380,7 +386,7 @@ module function plastic_dislotwin_init() result(myPlasticity) !-------------------------------------------------------------------------------------------------- ! allocate state arrays - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) sizeDotState = size(['rho_mob ','rho_dip ','gamma_sl']) * prm%sum_N_sl & + size(['f_tw']) * prm%sum_N_tw & + size(['f_tr']) * prm%sum_N_tr @@ -768,7 +774,7 @@ end subroutine dislotwin_dependentState !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- -module subroutine plastic_dislotwin_results(ph,group) +module subroutine plastic_dislotwin_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group @@ -783,30 +789,30 @@ module subroutine plastic_dislotwin_results(ph,group) select case(trim(prm%output(ou))) case('rho_mob') - call results_writeDataset(stt%rho_mob,group,trim(prm%output(ou)), & - 'mobile dislocation density','1/m²',prm%systems_sl) + call result_writeDataset(stt%rho_mob,group,trim(prm%output(ou)), & + 'mobile dislocation density','1/m²',prm%systems_sl) case('rho_dip') - call results_writeDataset(stt%rho_dip,group,trim(prm%output(ou)), & - 'dislocation dipole density','1/m²',prm%systems_sl) + call result_writeDataset(stt%rho_dip,group,trim(prm%output(ou)), & + 'dislocation dipole density','1/m²',prm%systems_sl) case('gamma_sl') - call results_writeDataset(stt%gamma_sl,group,trim(prm%output(ou)), & - 'plastic shear','1',prm%systems_sl) + call result_writeDataset(stt%gamma_sl,group,trim(prm%output(ou)), & + 'plastic shear','1',prm%systems_sl) case('Lambda_sl') - call results_writeDataset(dst%Lambda_sl,group,trim(prm%output(ou)), & - 'mean free path for slip','m',prm%systems_sl) + call result_writeDataset(dst%Lambda_sl,group,trim(prm%output(ou)), & + 'mean free path for slip','m',prm%systems_sl) case('tau_pass') - call results_writeDataset(dst%tau_pass,group,trim(prm%output(ou)), & - 'passing stress for slip','Pa',prm%systems_sl) + call result_writeDataset(dst%tau_pass,group,trim(prm%output(ou)), & + 'passing stress for slip','Pa',prm%systems_sl) case('f_tw') - call results_writeDataset(stt%f_tw,group,trim(prm%output(ou)), & - 'twinned volume fraction','m³/m³',prm%systems_tw) + call result_writeDataset(stt%f_tw,group,trim(prm%output(ou)), & + 'twinned volume fraction','m³/m³',prm%systems_tw) case('Lambda_tw') - call results_writeDataset(dst%Lambda_tw,group,trim(prm%output(ou)), & - 'mean free path for twinning','m',prm%systems_tw) + call result_writeDataset(dst%Lambda_tw,group,trim(prm%output(ou)), & + 'mean free path for twinning','m',prm%systems_tw) case('f_tr') - if (prm%sum_N_tr>0) call results_writeDataset(stt%f_tr,group,trim(prm%output(ou)), & + if (prm%sum_N_tr>0) call result_writeDataset(stt%f_tr,group,trim(prm%output(ou)), & 'martensite volume fraction','m³/m³') end select @@ -815,15 +821,15 @@ module subroutine plastic_dislotwin_results(ph,group) end associate -end subroutine plastic_dislotwin_results +end subroutine plastic_dislotwin_result !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on slip systems, their derivatives with respect to resolved ! stress, and the resolved stress. !> @details Derivatives and resolved stress are calculated only optionally. -! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to -! have the optional arguments at the end +! NOTE: Contrary to common convention, here the result (i.e. intent(out)) variables have to be put +! at the end since some of them are optional. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_sl(Mp,T,ph,en, & dot_gamma_sl,ddot_gamma_dtau_sl,tau_sl) @@ -898,8 +904,8 @@ end subroutine kinetics_sl !> @brief Calculate shear rates on twin systems and their derivatives with respect to resolved ! stress. !> @details Derivatives are calculated only optionally. -! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to -! have the optional arguments at the end. +! NOTE: Contrary to common convention, here the result (i.e. intent(out)) variables have to be put +! at the end since some of them are optional. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_tw(Mp,T,abs_dot_gamma_sl,ph,en,& dot_gamma_tw,ddot_gamma_dtau_tw) @@ -974,8 +980,8 @@ end subroutine kinetics_tw !> @brief Calculate shear rates on transformation systems and their derivatives with respect to ! resolved stress. !> @details Derivatives are calculated only optionally. -! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to -! have the optional arguments at the end. +! NOTE: Contrary to common convention, here the result (i.e. intent(out)) variables have to be put +! at the end since some of them are optional. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_tr(Mp,T,abs_dot_gamma_sl,ph,en,& dot_gamma_tr,ddot_gamma_dtau_tr) diff --git a/src/phase_mechanical_plastic_isotropic.f90 b/src/phase_mechanical_plastic_isotropic.f90 index c897c6c6d..7a94e6d8b 100644 --- a/src/phase_mechanical_plastic_isotropic.f90 +++ b/src/phase_mechanical_plastic_isotropic.f90 @@ -54,8 +54,9 @@ module function plastic_isotropic_init() result(myPlasticity) sizeState, sizeDotState real(pReal) :: & xi_0 !< initial critical stress - character(len=pStringLen) :: & - extmsg = '' + character(len=:), allocatable :: & + refs, & + extmsg type(tDict), pointer :: & phases, & phase, & @@ -72,9 +73,11 @@ module function plastic_isotropic_init() result(myPlasticity) print'(/,1x,a)', 'T. Maiti and P. Eisenlohr, Scripta Materialia 145:37–40, 2018' print'( 1x,a)', 'https://doi.org/10.1016/j.scriptamat.2017.09.047' + phases => config_material%get_dict('phase') allocate(param(phases%length)) allocate(state(phases%length)) + extmsg = '' do ph = 1, phases%length if (.not. myPlasticity(ph)) cycle @@ -85,6 +88,10 @@ module function plastic_isotropic_init() result(myPlasticity) mech => phase%get_dict('mechanical') pl => mech%get_dict('plastic') + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(pl,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs + #if defined (__GFORTRAN__) prm%output = output_as1dString(pl) #else @@ -105,7 +112,7 @@ module function plastic_isotropic_init() result(myPlasticity) prm%c_2 = pl%get_asFloat('c_2', defaultVal=0.0_pReal) prm%a = pl%get_asFloat('a') - prm%dilatation = pl%get_AsBool('dilatation',defaultVal = .false.) + prm%dilatation = pl%get_asBool('dilatation',defaultVal = .false.) !-------------------------------------------------------------------------------------------------- ! sanity checks @@ -117,7 +124,7 @@ module function plastic_isotropic_init() result(myPlasticity) !-------------------------------------------------------------------------------------------------- ! allocate state arrays - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) sizeDotState = size(['xi']) sizeState = sizeDotState @@ -285,7 +292,7 @@ end function isotropic_dotState !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- -module subroutine plastic_isotropic_results(ph,group) +module subroutine plastic_isotropic_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group @@ -296,13 +303,13 @@ module subroutine plastic_isotropic_results(ph,group) outputsLoop: do o = 1,size(prm%output) select case(trim(prm%output(o))) case ('xi') - call results_writeDataset(stt%xi,group,trim(prm%output(o)), & - 'resistance against plastic flow','Pa') + call result_writeDataset(stt%xi,group,trim(prm%output(o)), & + 'resistance against plastic flow','Pa') end select end do outputsLoop end associate -end subroutine plastic_isotropic_results +end subroutine plastic_isotropic_result end submodule isotropic diff --git a/src/phase_mechanical_plastic_kinehardening.f90 b/src/phase_mechanical_plastic_kinehardening.f90 index 692501f42..390d5c7c8 100644 --- a/src/phase_mechanical_plastic_kinehardening.f90 +++ b/src/phase_mechanical_plastic_kinehardening.f90 @@ -2,8 +2,8 @@ !> @author Philip Eisenlohr, Michigan State University !> @author Zhuowen Zhao, Michigan State University !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH -!> @brief Phenomenological crystal plasticity using a power law formulation for the shear rates -!! and a Voce-type kinematic hardening rule +!> @brief Phenomenological crystal plasticity using a power-law formulation for the shear rates +!! and a Voce-type kinematic hardening rule. !-------------------------------------------------------------------------------------------------- submodule(phase:plastic) kinehardening @@ -12,14 +12,18 @@ submodule(phase:plastic) kinehardening n = 1.0_pReal, & !< stress exponent for slip dot_gamma_0 = 1.0_pReal !< reference shear strain rate for slip real(pReal), allocatable, dimension(:) :: & - h_0_f, & !< initial hardening rate of forward stress for each slip - h_inf_f, & !< asymptotic hardening rate of forward stress for each slip - h_0_b, & !< initial hardening rate of back stress for each slip - h_inf_b, & !< asymptotic hardening rate of back stress for each slip - xi_inf_f, & - xi_inf_b + h_0_xi, & !< initial hardening rate of forest stress per slip family + !! θ_0,for + h_0_chi, & !< initial hardening rate of back stress per slip family + !! θ_0,bs + h_inf_xi, & !< asymptotic hardening rate of forest stress per slip family + !! θ_1,for + h_inf_chi, & !< asymptotic hardening rate of back stress per slip family + !! θ_1,bs + xi_inf, & !< back-extrapolated forest stress from terminal linear hardening + chi_inf !< back-extrapolated back stress from terminal linear hardening real(pReal), allocatable, dimension(:,:) :: & - h_sl_sl !< slip resistance from slip activity + h_sl_sl !< slip resistance change per slip activity real(pReal), allocatable, dimension(:,:,:) :: & P, & P_nS_pos, & @@ -43,11 +47,15 @@ submodule(phase:plastic) kinehardening type :: tKinehardeningState real(pReal), pointer, dimension(:,:) :: & - xi, & !< resistance against plastic slip + xi, & !< forest stress + !! τ_for chi, & !< back stress - chi_0, & !< back stress at last switch of stress sense + !! τ_bs + chi_flip, & !< back stress at last reversal of stress sense + !! χ_0 gamma, & !< accumulated (absolute) shear - gamma_0, & !< accumulated shear at last switch of stress sense + gamma_flip, & !< accumulated shear at last reversal of stress sense + !! γ_0 sgn_gamma !< sense of acting shear stress (-1 or +1) end type tKinehardeningState @@ -75,16 +83,19 @@ module function plastic_kinehardening_init() result(myPlasticity) integer, dimension(:), allocatable :: & N_sl real(pReal), dimension(:), allocatable :: & - xi_0, & !< initial resistance against plastic flow + xi_0, & !< initial forest stress + !! τ_for,0 a !< non-Schmid coefficients - character(len=pStringLen) :: & - extmsg = '' + character(len=:), allocatable :: & + refs, & + extmsg type(tDict), pointer :: & phases, & phase, & mech, & pl + myPlasticity = plastic_active('kinehardening') if (count(myPlasticity) == 0) return @@ -94,12 +105,13 @@ module function plastic_kinehardening_init() result(myPlasticity) print'(/,1x,a)', 'J.A. Wollmershauser et al., International Journal of Fatigue 36:181–193, 2012' print'( 1x,a)', 'https://doi.org/10.1016/j.ijfatigue.2011.07.008' + phases => config_material%get_dict('phase') allocate(param(phases%length)) allocate(indexDotState(phases%length)) allocate(state(phases%length)) allocate(deltaState(phases%length)) - + extmsg = '' do ph = 1, phases%length if (.not. myPlasticity(ph)) cycle @@ -111,6 +123,10 @@ module function plastic_kinehardening_init() result(myPlasticity) mech => phase%get_dict('mechanical') pl => mech%get_dict('plastic') + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(pl,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs + #if defined (__GFORTRAN__) prm%output = output_as1dString(pl) #else @@ -126,8 +142,8 @@ module function plastic_kinehardening_init() result(myPlasticity) prm%P = lattice_SchmidMatrix_slip(N_sl,phase_lattice(ph),phase_cOverA(ph)) if (phase_lattice(ph) == 'cI') then - a = pl%get_as1dFloat('a_nonSchmid',defaultVal = emptyRealArray) - if (size(a) > 0) prm%nonSchmidActive = .true. + a = pl%get_as1dFloat('a_nonSchmid',defaultVal=emptyRealArray) + prm%nonSchmidActive = size(a) > 0 prm%P_nS_pos = lattice_nonSchmidMatrix(N_sl,a,+1) prm%P_nS_neg = lattice_nonSchmidMatrix(N_sl,a,-1) else @@ -137,45 +153,49 @@ module function plastic_kinehardening_init() result(myPlasticity) prm%h_sl_sl = lattice_interaction_SlipBySlip(N_sl,pl%get_as1dFloat('h_sl-sl'), & phase_lattice(ph)) - xi_0 = pl%get_as1dFloat('xi_0', requiredSize=size(N_sl)) - prm%xi_inf_f = pl%get_as1dFloat('xi_inf_f', requiredSize=size(N_sl)) - prm%xi_inf_b = pl%get_as1dFloat('xi_inf_b', requiredSize=size(N_sl)) - prm%h_0_f = pl%get_as1dFloat('h_0_f', requiredSize=size(N_sl)) - prm%h_inf_f = pl%get_as1dFloat('h_inf_f', requiredSize=size(N_sl)) - prm%h_0_b = pl%get_as1dFloat('h_0_b', requiredSize=size(N_sl)) - prm%h_inf_b = pl%get_as1dFloat('h_inf_b', requiredSize=size(N_sl)) + xi_0 = pl%get_as1dFloat('xi_0', requiredSize=size(N_sl)) + prm%xi_inf = pl%get_as1dFloat('xi_inf', requiredSize=size(N_sl)) + prm%chi_inf = pl%get_as1dFloat('chi_inf', requiredSize=size(N_sl)) + prm%h_0_xi = pl%get_as1dFloat('h_0_xi', requiredSize=size(N_sl)) + prm%h_0_chi = pl%get_as1dFloat('h_0_chi', requiredSize=size(N_sl)) + prm%h_inf_xi = pl%get_as1dFloat('h_inf_xi', requiredSize=size(N_sl)) + prm%h_inf_chi = pl%get_as1dFloat('h_inf_chi', requiredSize=size(N_sl)) prm%dot_gamma_0 = pl%get_asFloat('dot_gamma_0') prm%n = pl%get_asFloat('n') ! expand: family => system - xi_0 = math_expand(xi_0, N_sl) - prm%xi_inf_f = math_expand(prm%xi_inf_f, N_sl) - prm%xi_inf_b = math_expand(prm%xi_inf_b, N_sl) - prm%h_0_f = math_expand(prm%h_0_f, N_sl) - prm%h_inf_f = math_expand(prm%h_inf_f, N_sl) - prm%h_0_b = math_expand(prm%h_0_b, N_sl) - prm%h_inf_b = math_expand(prm%h_inf_b, N_sl) + xi_0 = math_expand(xi_0, N_sl) + prm%xi_inf = math_expand(prm%xi_inf, N_sl) + prm%chi_inf = math_expand(prm%chi_inf, N_sl) + prm%h_0_xi = math_expand(prm%h_0_xi, N_sl) + prm%h_0_chi = math_expand(prm%h_0_chi, N_sl) + prm%h_inf_xi = math_expand(prm%h_inf_xi, N_sl) + prm%h_inf_chi = math_expand(prm%h_inf_chi, N_sl) !-------------------------------------------------------------------------------------------------- ! sanity checks 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 (any(xi_0 <= 0.0_pReal)) extmsg = trim(extmsg)//' xi_0' - if (any(prm%xi_inf_f <= 0.0_pReal)) extmsg = trim(extmsg)//' xi_inf_f' - if (any(prm%xi_inf_b <= 0.0_pReal)) extmsg = trim(extmsg)//' xi_inf_b' + if (any(prm%xi_inf <= 0.0_pReal)) extmsg = trim(extmsg)//' xi_inf' + if (any(prm%chi_inf <= 0.0_pReal)) extmsg = trim(extmsg)//' chi_inf' else slipActive xi_0 = emptyRealArray - allocate(prm%xi_inf_f,prm%xi_inf_b,prm%h_0_f,prm%h_inf_f,prm%h_0_b,prm%h_inf_b,source=emptyRealArray) + allocate(prm%xi_inf,prm%chi_inf,prm%h_0_xi,prm%h_inf_xi,prm%h_0_chi,prm%h_inf_chi,source=emptyRealArray) allocate(prm%h_sl_sl(0,0)) end if slipActive !-------------------------------------------------------------------------------------------------- ! allocate state arrays - Nmembers = count(material_phaseID == ph) - sizeDotState = size(['xi ','chi ', 'gamma']) * prm%sum_N_sl - sizeDeltaState = size(['sgn_gamma', 'chi_0 ', 'gamma_0 ']) * prm%sum_N_sl + Nmembers = count(material_ID_phase == ph) + sizeDotState = prm%sum_N_sl * size(['xi ',& + 'chi ',& + 'gamma']) + sizeDeltaState = prm%sum_N_sl * size(['sgn_gamma ',& + 'chi_flip ',& + 'gamma_flip']) sizeState = sizeDotState + sizeDeltaState call phase_allocateState(plasticState(ph),Nmembers,sizeState,sizeDotState,sizeDeltaState) @@ -212,13 +232,13 @@ module function plastic_kinehardening_init() result(myPlasticity) startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl - stt%chi_0 => plasticState(ph)%state (startIndex :endIndex ,:) - dlt%chi_0 => plasticState(ph)%deltaState(startIndex-o:endIndex-o,:) + stt%chi_flip => plasticState(ph)%state (startIndex :endIndex ,:) + dlt%chi_flip => plasticState(ph)%deltaState(startIndex-o:endIndex-o,:) startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl - stt%gamma_0 => plasticState(ph)%state (startIndex :endIndex ,:) - dlt%gamma_0 => plasticState(ph)%deltaState(startIndex-o:endIndex-o,:) + stt%gamma_flip => plasticState(ph)%state (startIndex :endIndex ,:) + dlt%gamma_flip => plasticState(ph)%deltaState(startIndex-o:endIndex-o,:) end associate @@ -259,7 +279,7 @@ pure module subroutine kinehardening_LpAndItsTangent(Lp,dLp_dMp,Mp,ph,en) associate(prm => param(ph)) - call kinetics(Mp,ph,en,dot_gamma_pos,dot_gamma_neg,ddot_gamma_dtau_pos,ddot_gamma_dtau_neg) + call kinetics(Mp,ph,en, dot_gamma_pos,dot_gamma_neg,ddot_gamma_dtau_pos,ddot_gamma_dtau_neg) do i = 1, prm%sum_N_sl Lp = Lp + (dot_gamma_pos(i)+dot_gamma_neg(i))*prm%P(1:3,1:3,i) @@ -298,23 +318,24 @@ module function plastic_kinehardening_dotState(Mp,ph,en) result(dotState) dot_chi => dotState(IndexDotState(ph)%chi(1):IndexDotState(ph)%chi(2)),& dot_gamma => dotState(IndexDotState(ph)%gamma(1):IndexDotState(ph)%gamma(2))) - call kinetics(Mp,ph,en,dot_gamma_pos,dot_gamma_neg) + call kinetics(Mp,ph,en, dot_gamma_pos,dot_gamma_neg) dot_gamma = abs(dot_gamma_pos+dot_gamma_neg) sumGamma = sum(stt%gamma(:,en)) dot_xi = matmul(prm%h_sl_sl,dot_gamma) & - * ( prm%h_inf_f & - + (prm%h_0_f - prm%h_inf_f + prm%h_0_f*prm%h_inf_f*sumGamma/prm%xi_inf_f) & - * exp(-sumGamma*prm%h_0_f/prm%xi_inf_f) & - ) + * ( prm%h_inf_xi & + + ( prm%h_0_xi & + - prm%h_inf_xi * (1_pReal -sumGamma*prm%h_0_xi/prm%xi_inf) ) & + * exp(-sumGamma*prm%h_0_xi/prm%xi_inf) & + ) dot_chi = stt%sgn_gamma(:,en)*dot_gamma & - * ( prm%h_inf_b & - + (prm%h_0_b - prm%h_inf_b & - + prm%h_0_b*prm%h_inf_b/(prm%xi_inf_b+stt%chi_0(:,en))*(stt%gamma(:,en)-stt%gamma_0(:,en))& - ) *exp(-(stt%gamma(:,en)-stt%gamma_0(:,en)) *prm%h_0_b/(prm%xi_inf_b+stt%chi_0(:,en))) & - ) + * ( prm%h_inf_chi & + + ( prm%h_0_chi & + - prm%h_inf_chi*(1_pReal -(stt%gamma(:,en)-stt%gamma_flip(:,en))*prm%h_0_chi/(prm%chi_inf+stt%chi_flip(:,en))) ) & + * exp(-(stt%gamma(:,en)-stt%gamma_flip(:,en))*prm%h_0_chi/(prm%chi_inf+stt%chi_flip(:,en))) & + ) end associate @@ -339,19 +360,19 @@ module subroutine plastic_kinehardening_deltaState(Mp,ph,en) associate(prm => param(ph), stt => state(ph), dlt => deltaState(ph)) - call kinetics(Mp,ph,en,dot_gamma_pos,dot_gamma_neg) + call kinetics(Mp,ph,en, dot_gamma_pos,dot_gamma_neg) sgn_gamma = merge(state(ph)%sgn_gamma(:,en), & sign(1.0_pReal,dot_gamma_pos+dot_gamma_neg), & dEq0(dot_gamma_pos+dot_gamma_neg,1e-10_pReal)) where(dNeq(sgn_gamma,stt%sgn_gamma(:,en),0.1_pReal)) ! ToDo sgn_gamma*stt%sgn_gamma(:,en)<0 - dlt%sgn_gamma (:,en) = sgn_gamma - stt%sgn_gamma(:,en) - dlt%chi_0 (:,en) = abs(stt%chi(:,en)) - stt%chi_0(:,en) - dlt%gamma_0(:,en) = stt%gamma(:,en) - stt%gamma_0(:,en) + dlt%sgn_gamma (:,en) = sgn_gamma - stt%sgn_gamma (:,en) + dlt%chi_flip (:,en) = abs(stt%chi (:,en)) - stt%chi_flip (:,en) + dlt%gamma_flip(:,en) = stt%gamma(:,en) - stt%gamma_flip(:,en) else where dlt%sgn_gamma (:,en) = 0.0_pReal - dlt%chi_0 (:,en) = 0.0_pReal - dlt%gamma_0(:,en) = 0.0_pReal + dlt%chi_flip (:,en) = 0.0_pReal + dlt%gamma_flip(:,en) = 0.0_pReal end where end associate @@ -362,7 +383,7 @@ end subroutine plastic_kinehardening_deltaState !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- -module subroutine plastic_kinehardening_results(ph,group) +module subroutine plastic_kinehardening_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group @@ -377,38 +398,38 @@ module subroutine plastic_kinehardening_results(ph,group) select case(trim(prm%output(ou))) case ('xi') - call results_writeDataset(stt%xi,group,trim(prm%output(ou)), & - 'resistance against plastic slip','Pa',prm%systems_sl) + call result_writeDataset(stt%xi,group,trim(prm%output(ou)), & + 'forest stress','Pa',prm%systems_sl) case ('chi') - call results_writeDataset(stt%chi,group,trim(prm%output(ou)), & - 'back stress','Pa',prm%systems_sl) + call result_writeDataset(stt%chi,group,trim(prm%output(ou)), & + 'back stress','Pa',prm%systems_sl) case ('sgn(gamma)') - call results_writeDataset(int(stt%sgn_gamma),group,trim(prm%output(ou)), & - 'sense of shear','1',prm%systems_sl) - case ('chi_0') - call results_writeDataset(stt%chi_0,group,trim(prm%output(ou)), & - 'back stress at last switch of stress sense','Pa',prm%systems_sl) - case ('gamma_0') - call results_writeDataset(stt%gamma_0,group,trim(prm%output(ou)), & - 'plastic shear at last switch of stress sense','1',prm%systems_sl) + call result_writeDataset(int(stt%sgn_gamma),group,trim(prm%output(ou)), & + 'sense of shear','1',prm%systems_sl) + case ('chi_flip') + call result_writeDataset(stt%chi_flip,group,trim(prm%output(ou)), & + 'back stress at last reversal of stress sense','Pa',prm%systems_sl) + case ('gamma_flip') + call result_writeDataset(stt%gamma_flip,group,trim(prm%output(ou)), & + 'plastic shear at last reversal of stress sense','1',prm%systems_sl) case ('gamma') - call results_writeDataset(stt%gamma,group,trim(prm%output(ou)), & - 'plastic shear','1',prm%systems_sl) + call result_writeDataset(stt%gamma,group,trim(prm%output(ou)), & + 'plastic shear','1',prm%systems_sl) end select end do end associate -end subroutine plastic_kinehardening_results +end subroutine plastic_kinehardening_result !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on slip systems and their derivatives with respect to resolved ! stress. !> @details: Derivatives are calculated only optionally. -! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to -! have the optional arguments at the end. +! NOTE: Contrary to common convention, here the result (i.e. intent(out)) variables have to be put +! at the end since some of them are optional. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics(Mp,ph,en, & dot_gamma_pos,dot_gamma_neg,ddot_gamma_dtau_pos,ddot_gamma_dtau_neg) diff --git a/src/phase_mechanical_plastic_none.f90 b/src/phase_mechanical_plastic_none.f90 index 711260531..b79a61183 100644 --- a/src/phase_mechanical_plastic_none.f90 +++ b/src/phase_mechanical_plastic_none.f90 @@ -27,10 +27,12 @@ module function plastic_none_init() result(myPlasticity) print'(/,1x,a)', '<<<+- phase:mechanical:plastic:none init -+>>>' print'(/,a,i0)', ' # phases: ',count(myPlasticity); flush(IO_STDOUT) + phases => config_material%get_dict('phase') do ph = 1, phases%length if (.not. myPlasticity(ph)) cycle - call phase_allocateState(plasticState(ph),count(material_phaseID == ph),0,0,0) + print'(a,i0,a)', ' phase ',ph + call phase_allocateState(plasticState(ph),count(material_ID_phase == ph),0,0,0) end do end function plastic_none_init diff --git a/src/phase_mechanical_plastic_nonlocal.f90 b/src/phase_mechanical_plastic_nonlocal.f90 index 2570014fb..aeb647eeb 100644 --- a/src/phase_mechanical_plastic_nonlocal.f90 +++ b/src/phase_mechanical_plastic_nonlocal.f90 @@ -188,8 +188,9 @@ module function plastic_nonlocal_init() result(myPlasticity) s, t, l real(pReal), dimension(:), allocatable :: & a - character(len=pStringLen) :: & - extmsg = '' + character(len=:), allocatable :: & + refs, & + extmsg type(tInitialParameters) :: & ini type(tDict), pointer :: & @@ -201,7 +202,7 @@ module function plastic_nonlocal_init() result(myPlasticity) myPlasticity = plastic_active('nonlocal') Ninstances = count(myPlasticity) if (Ninstances == 0) then - call geometry_plastic_nonlocal_disable + call geometry_plastic_nonlocal_disable() return end if @@ -216,15 +217,14 @@ module function plastic_nonlocal_init() result(myPlasticity) phases => config_material%get_dict('phase') - allocate(geom(phases%length)) - allocate(param(phases%length)) allocate(state(phases%length)) allocate(state0(phases%length)) allocate(dotState(phases%length)) allocate(deltaState(phases%length)) allocate(dependentState(phases%length)) + extmsg = '' do ph = 1, phases%length if (.not. myPlasticity(ph)) cycle @@ -236,13 +236,17 @@ module function plastic_nonlocal_init() result(myPlasticity) mech => phase%get_dict('mechanical') pl => mech%get_dict('plastic') - plasticState(ph)%nonlocal = pl%get_asBool('flux',defaultVal=.True.) + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(pl,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs + #if defined (__GFORTRAN__) prm%output = output_as1dString(pl) #else prm%output = pl%get_as1dString('output',defaultVal=emptyStringArray) #endif + plasticState(ph)%nonlocal = pl%get_asBool('flux',defaultVal=.True.) prm%isotropic_bound = pl%get_asString('isotropic_bound',defaultVal='isostrain') prm%atol_rho = pl%get_asFloat('atol_rho',defaultVal=1.0_pReal) @@ -396,7 +400,7 @@ module function plastic_nonlocal_init() result(myPlasticity) !-------------------------------------------------------------------------------------------------- ! allocate state arrays - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) sizeDotState = size([ 'rhoSglEdgePosMobile ','rhoSglEdgeNegMobile ', & 'rhoSglScrewPosMobile ','rhoSglScrewNegMobile ', & 'rhoSglEdgePosImmobile ','rhoSglEdgeNegImmobile ', & @@ -524,7 +528,7 @@ module function plastic_nonlocal_init() result(myPlasticity) if (.not. myPlasticity(ph)) cycle phase => phases%get_dict(ph) - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) l = 0 do t = 1,4 do s = 1,param(ph)%sum_N_sl @@ -664,8 +668,8 @@ module subroutine nonlocal_dependentState(ph, en) neighbor_ip = geom(ph)%IPneighborhood(2,n,en) if (neighbor_el > 0 .and. neighbor_ip > 0) then - if (material_phaseID(1,(neighbor_el-1)*discretization_nIPs + neighbor_ip) == ph) then - no = material_phaseEntry(1,(neighbor_el-1)*discretization_nIPs + neighbor_ip) + if (material_ID_phase(1,(neighbor_el-1)*discretization_nIPs + neighbor_ip) == ph) then + no = material_entry_phase(1,(neighbor_el-1)*discretization_nIPs + neighbor_ip) nRealNeighbors = nRealNeighbors + 1.0_pReal rho_neighbor0 = getRho0(ph,no) @@ -1116,12 +1120,6 @@ module subroutine nonlocal_dotState(Mp,timestep, & if ( any(rho(:,mob) + rhoDot(:,1:4) * timestep < -prm%atol_rho) & .or. any(rho(:,dip) + rhoDot(:,9:10) * timestep < -prm%atol_rho)) then -#ifdef DEBUG - if (debugConstitutive%extensive) then - print'(a,i5,a,i2)', '<< CONST >> evolution rate leads to negative density at ph ',ph,' en ',en - print'(a)', '<< CONST >> enforcing cutback !!!' - end if -#endif plasticState(ph)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) else dot%rho(:,en) = pack(rhoDot,.true.) @@ -1221,17 +1219,6 @@ function rhoDotFlux(timestep,ph,en) if (any( abs(dot_gamma) > 0.0_pReal & ! any active slip system ... .and. prm%C_CFL * abs(v0) * timestep & > geom(ph)%V_0(en)/ maxval(geom(ph)%IParea(:,en)))) then ! ...with velocity above critical value (we use the reference volume and area for simplicity here) -#ifdef DEBUG - if (debugConstitutive%extensive) then - print'(a,i5,a,i2)', '<< CONST >> CFL condition not fullfilled at ph ',ph,' en ',en - print'(a,e10.3,a,e10.3)', '<< CONST >> velocity is at ', & - maxval(abs(v0), abs(dot_gamma) > 0.0_pReal & - .and. prm%C_CFL * abs(v0) * timestep & - > geom(ph)%V_0(en) / maxval(geom(ph)%IParea(:,en))), & - ' at a timestep of ',timestep - print*, '<< CONST >> enforcing cutback !!!' - end if -#endif rhoDotFlux = IEEE_value(1.0_pReal,IEEE_quiet_NaN) ! enforce cutback return end if @@ -1253,8 +1240,8 @@ function rhoDotFlux(timestep,ph,en) neighbor_el = geom(ph)%IPneighborhood(1,n,en) neighbor_ip = geom(ph)%IPneighborhood(2,n,en) neighbor_n = geom(ph)%IPneighborhood(3,n,en) - np = material_phaseID(1,(neighbor_el-1)*discretization_nIPs + neighbor_ip) - no = material_phaseEntry(1,(neighbor_el-1)*discretization_nIPs + neighbor_ip) + np = material_ID_phase(1,(neighbor_el-1)*discretization_nIPs + neighbor_ip) + no = material_entry_phase(1,(neighbor_el-1)*discretization_nIPs + neighbor_ip) opposite_neighbor = n + mod(n,2) - mod(n+1,2) opposite_el = geom(ph)%IPneighborhood(1,opposite_neighbor,en) @@ -1401,7 +1388,7 @@ module subroutine plastic_nonlocal_updateCompatibility(orientation,ph,ip,el) associate(prm => param(ph)) ns = prm%sum_N_sl - en = material_phaseEntry(1,(el-1)*discretization_nIPs + ip) + en = material_entry_phase(1,(el-1)*discretization_nIPs + ip) !*** start out fully compatible my_compatibility = 0.0_pReal forall(s1 = 1:ns) my_compatibility(:,s1,s1,:) = 1.0_pReal @@ -1409,8 +1396,8 @@ module subroutine plastic_nonlocal_updateCompatibility(orientation,ph,ip,el) neighbors: do n = 1,nIPneighbors neighbor_e = IPneighborhood(1,n,ip,el) neighbor_i = IPneighborhood(2,n,ip,el) - neighbor_me = material_phaseEntry(1,(neighbor_e-1)*discretization_nIPs + neighbor_i) - neighbor_phase = material_phaseID(1,(neighbor_e-1)*discretization_nIPs + neighbor_i) + neighbor_me = material_entry_phase(1,(neighbor_e-1)*discretization_nIPs + neighbor_i) + neighbor_phase = material_ID_phase(1,(neighbor_e-1)*discretization_nIPs + neighbor_i) if (neighbor_e <= 0 .or. neighbor_i <= 0) then !* FREE SURFACE @@ -1469,7 +1456,7 @@ module subroutine plastic_nonlocal_updateCompatibility(orientation,ph,ip,el) end do neighbors - dependentState(ph)%compatibility(:,:,:,:,material_phaseEntry(1,(el-1)*discretization_nIPs + ip)) = my_compatibility + dependentState(ph)%compatibility(:,:,:,:,material_entry_phase(1,(el-1)*discretization_nIPs + ip)) = my_compatibility end associate @@ -1479,7 +1466,7 @@ end subroutine plastic_nonlocal_updateCompatibility !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- -module subroutine plastic_nonlocal_results(ph,group) +module subroutine plastic_nonlocal_result(ph,group) integer, intent(in) :: ph character(len=*),intent(in) :: group @@ -1493,63 +1480,63 @@ module subroutine plastic_nonlocal_results(ph,group) select case(trim(prm%output(ou))) case('rho_u_ed_pos') - call results_writeDataset(stt%rho_sgl_mob_edg_pos,group,trim(prm%output(ou)), & - 'positive mobile edge density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_sgl_mob_edg_pos,group,trim(prm%output(ou)), & + 'positive mobile edge density','1/m²', prm%systems_sl) case('rho_b_ed_pos') - call results_writeDataset(stt%rho_sgl_imm_edg_pos,group,trim(prm%output(ou)), & - 'positive immobile edge density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_sgl_imm_edg_pos,group,trim(prm%output(ou)), & + 'positive immobile edge density','1/m²', prm%systems_sl) case('rho_u_ed_neg') - call results_writeDataset(stt%rho_sgl_mob_edg_neg,group,trim(prm%output(ou)), & - 'negative mobile edge density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_sgl_mob_edg_neg,group,trim(prm%output(ou)), & + 'negative mobile edge density','1/m²', prm%systems_sl) case('rho_b_ed_neg') - call results_writeDataset(stt%rho_sgl_imm_edg_neg,group,trim(prm%output(ou)), & - 'negative immobile edge density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_sgl_imm_edg_neg,group,trim(prm%output(ou)), & + 'negative immobile edge density','1/m²', prm%systems_sl) case('rho_d_ed') - call results_writeDataset(stt%rho_dip_edg,group,trim(prm%output(ou)), & - 'edge dipole density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_dip_edg,group,trim(prm%output(ou)), & + 'edge dipole density','1/m²', prm%systems_sl) case('rho_u_sc_pos') - call results_writeDataset(stt%rho_sgl_mob_scr_pos,group,trim(prm%output(ou)), & - 'positive mobile screw density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_sgl_mob_scr_pos,group,trim(prm%output(ou)), & + 'positive mobile screw density','1/m²', prm%systems_sl) case('rho_b_sc_pos') - call results_writeDataset(stt%rho_sgl_imm_scr_pos,group,trim(prm%output(ou)), & - 'positive immobile screw density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_sgl_imm_scr_pos,group,trim(prm%output(ou)), & + 'positive immobile screw density','1/m²', prm%systems_sl) case('rho_u_sc_neg') - call results_writeDataset(stt%rho_sgl_mob_scr_neg,group,trim(prm%output(ou)), & - 'negative mobile screw density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_sgl_mob_scr_neg,group,trim(prm%output(ou)), & + 'negative mobile screw density','1/m²', prm%systems_sl) case('rho_b_sc_neg') - call results_writeDataset(stt%rho_sgl_imm_scr_neg,group,trim(prm%output(ou)), & - 'negative immobile screw density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_sgl_imm_scr_neg,group,trim(prm%output(ou)), & + 'negative immobile screw density','1/m²', prm%systems_sl) case('rho_d_sc') - call results_writeDataset(stt%rho_dip_scr,group,trim(prm%output(ou)), & - 'screw dipole density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_dip_scr,group,trim(prm%output(ou)), & + 'screw dipole density','1/m²', prm%systems_sl) case('rho_f') - call results_writeDataset(stt%rho_forest,group,trim(prm%output(ou)), & - 'forest density','1/m²', prm%systems_sl) + call result_writeDataset(stt%rho_forest,group,trim(prm%output(ou)), & + 'forest density','1/m²', prm%systems_sl) case('v_ed_pos') - call results_writeDataset(stt%v_edg_pos,group,trim(prm%output(ou)), & - 'positive edge velocity','m/s', prm%systems_sl) + call result_writeDataset(stt%v_edg_pos,group,trim(prm%output(ou)), & + 'positive edge velocity','m/s', prm%systems_sl) case('v_ed_neg') - call results_writeDataset(stt%v_edg_neg,group,trim(prm%output(ou)), & - 'negative edge velocity','m/s', prm%systems_sl) + call result_writeDataset(stt%v_edg_neg,group,trim(prm%output(ou)), & + 'negative edge velocity','m/s', prm%systems_sl) case('v_sc_pos') - call results_writeDataset(stt%v_scr_pos,group,trim(prm%output(ou)), & - 'positive srew velocity','m/s', prm%systems_sl) + call result_writeDataset(stt%v_scr_pos,group,trim(prm%output(ou)), & + 'positive srew velocity','m/s', prm%systems_sl) case('v_sc_neg') - call results_writeDataset(stt%v_scr_neg,group,trim(prm%output(ou)), & - 'negative screw velocity','m/s', prm%systems_sl) + call result_writeDataset(stt%v_scr_neg,group,trim(prm%output(ou)), & + 'negative screw velocity','m/s', prm%systems_sl) case('gamma') - call results_writeDataset(stt%gamma,group,trim(prm%output(ou)), & - 'plastic shear','1', prm%systems_sl) + call result_writeDataset(stt%gamma,group,trim(prm%output(ou)), & + 'plastic shear','1', prm%systems_sl) case('tau_pass') - call results_writeDataset(dst%tau_pass,group,trim(prm%output(ou)), & - 'passing stress for slip','Pa', prm%systems_sl) + call result_writeDataset(dst%tau_pass,group,trim(prm%output(ou)), & + 'passing stress for slip','Pa', prm%systems_sl) end select end do end associate -end subroutine plastic_nonlocal_results +end subroutine plastic_nonlocal_result !-------------------------------------------------------------------------------------------------- @@ -1774,14 +1761,14 @@ subroutine storeGeometry(ph) areaNormal = reshape(IPareaNormal,[3,nIPneighbors,nCell]) coords = reshape(discretization_IPcoords,[3,nCell]) - do ce = 1, size(material_homogenizationEntry,1) + do ce = 1, size(material_entry_homogenization,1) do co = 1, homogenization_maxNconstituents - if (material_phaseID(co,ce) == ph) then - geom(ph)%V_0(material_phaseEntry(co,ce)) = V(ce) - geom(ph)%IPneighborhood(:,:,material_phaseEntry(co,ce)) = neighborhood(:,:,ce) - geom(ph)%IParea(:,material_phaseEntry(co,ce)) = area(:,ce) - geom(ph)%IPareaNormal(:,:,material_phaseEntry(co,ce)) = areaNormal(:,:,ce) - geom(ph)%IPcoordinates(:,material_phaseEntry(co,ce)) = coords(:,ce) + if (material_ID_phase(co,ce) == ph) then + geom(ph)%V_0(material_entry_phase(co,ce)) = V(ce) + geom(ph)%IPneighborhood(:,:,material_entry_phase(co,ce)) = neighborhood(:,:,ce) + geom(ph)%IParea(:,material_entry_phase(co,ce)) = area(:,ce) + geom(ph)%IPareaNormal(:,:,material_entry_phase(co,ce)) = areaNormal(:,:,ce) + geom(ph)%IPcoordinates(:,material_entry_phase(co,ce)) = coords(:,ce) end if end do end do diff --git a/src/phase_mechanical_plastic_phenopowerlaw.f90 b/src/phase_mechanical_plastic_phenopowerlaw.f90 index 04ddbe13c..11556db78 100644 --- a/src/phase_mechanical_plastic_phenopowerlaw.f90 +++ b/src/phase_mechanical_plastic_phenopowerlaw.f90 @@ -85,13 +85,15 @@ module function plastic_phenopowerlaw_init() result(myPlasticity) sizeState, sizeDotState, & startIndex, endIndex integer, dimension(:), allocatable :: & - N_sl, N_tw + N_sl, & !< number of slip-systems for a given slip family + N_tw !< number of twin-systems for a given twin family real(pReal), dimension(:), allocatable :: & xi_0_sl, & !< initial critical shear stress for slip xi_0_tw, & !< initial critical shear stress for twin a !< non-Schmid coefficients - character(len=pStringLen) :: & - extmsg = '' + character(len=:), allocatable :: & + refs, & + extmsg type(tDict), pointer :: & phases, & phase, & @@ -110,6 +112,7 @@ module function plastic_phenopowerlaw_init() result(myPlasticity) allocate(param(phases%length)) allocate(indexDotState(phases%length)) allocate(state(phases%length)) + extmsg = '' do ph = 1, phases%length if (.not. myPlasticity(ph)) cycle @@ -121,6 +124,16 @@ module function plastic_phenopowerlaw_init() result(myPlasticity) mech => phase%get_dict('mechanical') pl => mech%get_dict('plastic') + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(pl,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs + +#if defined (__GFORTRAN__) + prm%output = output_as1dString(pl) +#else + prm%output = pl%get_as1dString('output',defaultVal=emptyStringArray) +#endif + !-------------------------------------------------------------------------------------------------- ! slip related parameters N_sl = pl%get_as1dInt('N_sl',defaultVal=emptyIntArray) @@ -216,18 +229,9 @@ module function plastic_phenopowerlaw_init() result(myPlasticity) prm%h_0_tw_sl = 0.0_pReal end if slipAndTwinActive -!-------------------------------------------------------------------------------------------------- -! output pararameters - -#if defined (__GFORTRAN__) - prm%output = output_as1dString(pl) -#else - prm%output = pl%get_as1dString('output',defaultVal=emptyStringArray) -#endif - !-------------------------------------------------------------------------------------------------- ! allocate state arrays - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) sizeDotState = size(['xi_sl ','gamma_sl']) * prm%sum_N_sl & + size(['xi_tw ','gamma_tw']) * prm%sum_N_tw sizeState = sizeDotState @@ -278,7 +282,7 @@ end function plastic_phenopowerlaw_init !-------------------------------------------------------------------------------------------------- !> @brief Calculate plastic velocity gradient and its tangent. -!> @details asummes that deformation by dislocation glide affects twinned and untwinned volume +!> @details assumes that deformation by dislocation glide affects twinned and untwinned volume ! equally (Taylor assumption). Twinning happens only in untwinned volume !-------------------------------------------------------------------------------------------------- pure module subroutine phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,ph,en) @@ -380,7 +384,7 @@ end function phenopowerlaw_dotState !-------------------------------------------------------------------------------------------------- !> @brief Write results to HDF5 output file. !-------------------------------------------------------------------------------------------------- -module subroutine plastic_phenopowerlaw_results(ph,group) +module subroutine plastic_phenopowerlaw_result(ph,group) integer, intent(in) :: ph character(len=*), intent(in) :: group @@ -395,18 +399,18 @@ module subroutine plastic_phenopowerlaw_results(ph,group) select case(trim(prm%output(ou))) case('xi_sl') - call results_writeDataset(stt%xi_sl,group,trim(prm%output(ou)), & - 'resistance against plastic slip','Pa',prm%systems_sl) + call result_writeDataset(stt%xi_sl,group,trim(prm%output(ou)), & + 'resistance against plastic slip','Pa',prm%systems_sl) case('gamma_sl') - call results_writeDataset(stt%gamma_sl,group,trim(prm%output(ou)), & - 'plastic shear','1',prm%systems_sl) + call result_writeDataset(stt%gamma_sl,group,trim(prm%output(ou)), & + 'plastic shear','1',prm%systems_sl) case('xi_tw') - call results_writeDataset(stt%xi_tw,group,trim(prm%output(ou)), & - 'resistance against twinning','Pa',prm%systems_tw) + call result_writeDataset(stt%xi_tw,group,trim(prm%output(ou)), & + 'resistance against twinning','Pa',prm%systems_tw) case('gamma_tw') - call results_writeDataset(stt%gamma_tw,group,trim(prm%output(ou)), & - 'twinning shear','1',prm%systems_tw) + call result_writeDataset(stt%gamma_tw,group,trim(prm%output(ou)), & + 'twinning shear','1',prm%systems_tw) end select @@ -414,15 +418,15 @@ module subroutine plastic_phenopowerlaw_results(ph,group) end associate -end subroutine plastic_phenopowerlaw_results +end subroutine plastic_phenopowerlaw_result !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on slip systems and their derivatives with respect to resolved ! stress. !> @details Derivatives are calculated only optionally. -! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to -! have the optional arguments at the end. +! NOTE: Contrary to common convention, here the result (i.e. intent(out)) variables have to be put +! at the end since some of them are optional. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_sl(Mp,ph,en, & dot_gamma_sl_pos,dot_gamma_sl_neg,ddot_gamma_dtau_sl_pos,ddot_gamma_dtau_sl_neg) @@ -489,10 +493,10 @@ end subroutine kinetics_sl !-------------------------------------------------------------------------------------------------- !> @brief Calculate shear rates on twin systems and their derivatives with respect to resolved -! stress. Twinning is assumed to take place only in untwinned volume. -!> @details Derivatives are calculated only optionally. -! NOTE: Against the common convention, the result (i.e. intent(out)) variables are the last to -! have the optional arguments at the end. +! stress. Twinning is assumed to take place only in an untwinned volume. +!> @details Derivatives are calculated and returned if corresponding output variables are present in the argument list. +! NOTE: Contrary to common convention, here the result (i.e. intent(out)) variables have to be put +! at the end since some of them are optional. !-------------------------------------------------------------------------------------------------- pure subroutine kinetics_tw(Mp,ph,en,& dot_gamma_tw,ddot_gamma_dtau_tw) diff --git a/src/phase_thermal.f90 b/src/phase_thermal.f90 index fd79d3d46..1371f3b7f 100644 --- a/src/phase_thermal.f90 +++ b/src/phase_thermal.f90 @@ -84,7 +84,7 @@ module subroutine thermal_init(phases) thermal type(tList), pointer :: & sources - + character(len=:), allocatable :: refs integer :: & ph, so, & Nmembers @@ -93,13 +93,12 @@ module subroutine thermal_init(phases) print'(/,1x,a)', '<<<+- phase:thermal init -+>>>' allocate(current(phases%length)) - allocate(thermalState(phases%length)) allocate(thermal_Nsources(phases%length),source = 0) allocate(param(phases%length)) do ph = 1, phases%length - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) allocate(current(ph)%T(Nmembers),source=T_ROOM) allocate(current(ph)%dot_T(Nmembers),source=0.0_pReal) phase => phases%get_dict(ph) @@ -107,6 +106,9 @@ module subroutine thermal_init(phases) ! ToDo: temperature dependency of K and C_p if (thermal%length > 0) then + print'(/,1x,a,i0,a)', 'phase ',ph,': '//phases%key(ph) + refs = config_listReferences(thermal,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs param(ph)%C_p = thermal%get_asFloat('C_p') param(ph)%K(1,1) = thermal%get_asFloat('K_11') if (any(phase_lattice(ph) == ['hP','tI'])) param(ph)%K(3,3) = thermal%get_asFloat('K_33') @@ -212,8 +214,8 @@ module function phase_mu_T(co,ce) result(mu) real(pReal) :: mu - mu = phase_rho(material_phaseID(co,ce)) & - * param(material_phaseID(co,ce))%C_p + mu = phase_rho(material_ID_phase(co,ce)) & + * param(material_ID_phase(co,ce))%C_p end function phase_mu_T @@ -227,7 +229,7 @@ module function phase_K_T(co,ce) result(K) real(pReal), dimension(3,3) :: K - K = crystallite_push33ToRef(co,ce,param(material_phaseID(co,ce))%K) + K = crystallite_push33ToRef(co,ce,param(material_ID_phase(co,ce))%K) end function phase_K_T @@ -352,8 +354,8 @@ module subroutine phase_thermal_setField(T,dot_T, co,ce) integer, intent(in) :: ce, co - current(material_phaseID(co,ce))%T(material_phaseEntry(co,ce)) = T - current(material_phaseID(co,ce))%dot_T(material_phaseEntry(co,ce)) = dot_T + current(material_ID_phase(co,ce))%T(material_entry_phase(co,ce)) = T + current(material_ID_phase(co,ce))%dot_T(material_entry_phase(co,ce)) = dot_T end subroutine phase_thermal_setField @@ -394,9 +396,9 @@ end function thermal_active !---------------------------------------------------------------------------------------------- -!< @brief writes thermal sources results to HDF5 output file +!< @brief Write thermal sources results to HDF5 output file. !---------------------------------------------------------------------------------------------- -module subroutine thermal_results(group,ph) +module subroutine thermal_result(group,ph) character(len=*), intent(in) :: group integer, intent(in) :: ph @@ -406,20 +408,20 @@ module subroutine thermal_results(group,ph) if (.not. allocated(param(ph)%output)) return - call results_closeGroup(results_addGroup(group//'thermal')) + call result_closeGroup(result_addGroup(group//'thermal')) do ou = 1, size(param(ph)%output) select case(trim(param(ph)%output(ou))) case ('T') - call results_writeDataset(current(ph)%T,group//'thermal','T', 'temperature','K') + call result_writeDataset(current(ph)%T,group//'thermal','T', 'temperature','K') end select end do -end subroutine thermal_results +end subroutine thermal_result end submodule thermal diff --git a/src/phase_thermal_dissipation.f90 b/src/phase_thermal_dissipation.f90 index 5cd2d4d90..66bde6808 100644 --- a/src/phase_thermal_dissipation.f90 +++ b/src/phase_thermal_dissipation.f90 @@ -1,6 +1,7 @@ !-------------------------------------------------------------------------------------------------- !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH +!> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for thermal source due to plastic dissipation !> @details to be done !-------------------------------------------------------------------------------------------------- @@ -33,11 +34,13 @@ module function dissipation_init(source_length) result(mySources) src class(tList), pointer :: & sources + character(len=:), allocatable :: refs integer :: so,Nmembers,ph mySources = thermal_active('dissipation',source_length) if (count(mySources) == 0) return + print'(/,1x,a)', '<<<+- phase:thermal:dissipation init -+>>>' print'(/,a,i2)', ' # phases: ',count(mySources); flush(IO_STDOUT) @@ -54,9 +57,12 @@ module function dissipation_init(source_length) result(mySources) if (mySources(so,ph)) then associate(prm => param(ph)) src => sources%get_dict(so) + print'(1x,a,i0,a,i0)', 'phase ',ph,' source ',so + refs = config_listReferences(src,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs prm%kappa = src%get_asFloat('kappa') - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) call phase_allocateState(thermalState(ph)%p(so),Nmembers,0,0,0) end associate @@ -76,10 +82,13 @@ module function dissipation_f_T(ph,en) result(f_T) integer, intent(in) :: ph, en real(pReal) :: & f_T + real(pReal), dimension(3,3) :: & + Mp !< Mandel stress work conjugate with Lp + Mp = matmul(matmul(transpose(mechanical_F_i(ph,en)),mechanical_F_i(ph,en)),mechanical_S(ph,en)) associate(prm => param(ph)) - f_T = prm%kappa*sum(abs(mechanical_S(ph,en)*mechanical_L_p(ph,en))) + f_T = prm%kappa*sum(abs(Mp*mechanical_L_p(ph,en))) end associate end function dissipation_f_T diff --git a/src/phase_thermal_externalheat.f90 b/src/phase_thermal_externalheat.f90 index 5970a5894..304171c10 100644 --- a/src/phase_thermal_externalheat.f90 +++ b/src/phase_thermal_externalheat.f90 @@ -36,11 +36,13 @@ module function externalheat_init(source_length) result(mySources) src type(tList), pointer :: & sources + character(len=:), allocatable :: refs integer :: so,Nmembers,ph mySources = thermal_active('externalheat',source_length) if (count(mySources) == 0) return + print'(/,1x,a)', '<<<+- phase:thermal:externalheat init -+>>>' print'(/,a,i2)', ' # phases: ',count(mySources); flush(IO_STDOUT) @@ -59,10 +61,13 @@ module function externalheat_init(source_length) result(mySources) source_thermal_externalheat_offset(ph) = so associate(prm => param(ph)) src => sources%get_dict(so) + print'(1x,a,i0,a,i0)', 'phase ',ph,' source ',so + refs = config_listReferences(src,indent=3) + if (len(refs) > 0) print'(/,1x,a)', refs prm%f = table(src,'t','f') - Nmembers = count(material_phaseID == ph) + Nmembers = count(material_ID_phase == ph) call phase_allocateState(thermalState(ph)%p(so),Nmembers,1,1,0) end associate end if diff --git a/src/prec.f90 b/src/prec.f90 index 1ae7ec62d..a3ec72251 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -41,8 +41,6 @@ module prec real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] character(len=pStringLen), dimension(0), parameter :: emptyStringArray = [character(len=pStringLen)::] - private :: & - selfTest contains @@ -62,7 +60,7 @@ subroutine prec_init() print'( a,e10.3)', ' epsilon value: ',PREAL_EPSILON print'( a,i3)', ' decimal precision: ',precision(0.0_pReal) - call selfTest() + call prec_selfTest() end subroutine prec_init @@ -247,7 +245,7 @@ end function prec_bytesToC_INT64_T !-------------------------------------------------------------------------------------------------- !> @brief Check correctness of some prec functions. !-------------------------------------------------------------------------------------------------- -subroutine selfTest() +subroutine prec_selfTest() integer, allocatable, dimension(:) :: realloc_lhs_test real(pReal), dimension(1) :: f @@ -281,6 +279,6 @@ subroutine selfTest() i = int(prec_bytesToC_INT64_T(int([+126,+23,+52,+1,0,0,0,0],C_SIGNED_CHAR)),pI64) if (i(1) /= 20191102_pI64) error stop 'prec_bytesToC_INT64_T' -end subroutine selfTest +end subroutine prec_selfTest end module prec diff --git a/src/quit.f90 b/src/quit.f90 index 4fc6bf11b..4395aa24d 100644 --- a/src/quit.f90 +++ b/src/quit.f90 @@ -5,6 +5,7 @@ !> everything is fine. Exit code 1 signals an error, message according to IO_error. !-------------------------------------------------------------------------------------------------- subroutine quit(stop_id) + use, intrinsic :: ISO_fortran_env, only: ERROR_UNIT #include use PETScSys #if (PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>14) && !defined(PETSC_HAVE_MPI_F90MODULE_VISIBILITY) @@ -22,23 +23,16 @@ subroutine quit(stop_id) integer, dimension(8) :: dateAndTime integer :: err_HDF5 - integer(MPI_INTEGER_KIND) :: err_MPI + integer(MPI_INTEGER_KIND) :: err_MPI, worldsize PetscErrorCode :: err_PETSc - call h5open_f(err_HDF5) - if (err_HDF5 /= 0_MPI_INTEGER_KIND) write(6,'(a,i5)') ' Error in h5open_f ',err_HDF5 ! prevents error if not opened yet + + call h5open_f(err_HDF5) ! prevents error if not opened yet + if (err_HDF5 < 0) write(ERROR_UNIT,'(a,i5)') ' Error in h5open_f ',err_HDF5 call h5close_f(err_HDF5) - if (err_HDF5 /= 0_MPI_INTEGER_KIND) write(6,'(a,i5)') ' Error in h5close_f ',err_HDF5 + if (err_HDF5 < 0) write(ERROR_UNIT,'(a,i5)') ' Error in h5close_f ',err_HDF5 call PetscFinalize(err_PETSc) - CHKERRQ(err_PETSc) - -#ifdef _OPENMP - call MPI_finalize(err_MPI) - if (err_MPI /= 0_MPI_INTEGER_KIND) write(6,'(a,i5)') ' Error in MPI_finalize',err_MPI -#else - err_MPI = 0_MPI_INTEGER_KIND -#endif call date_and_time(values = dateAndTime) write(6,'(/,a)') ' DAMASK terminated on:' @@ -49,10 +43,15 @@ subroutine quit(stop_id) dateAndTime(6),':',& dateAndTime(7) - if (stop_id == 0 .and. & - err_HDF5 == 0 .and. & - err_MPI == 0_MPI_INTEGER_KIND .and. & - err_PETSC == 0) stop 0 ! normal termination - stop 1 ! error (message from IO_error) + if (stop_id == 0 .and. err_HDF5 == 0 .and. err_PETSC == 0) then + call MPI_Finalize(err_MPI) + if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI_Finalize error' + stop 0 ! normal termination + else + call MPI_Comm_size(MPI_COMM_WORLD,worldsize,err_MPI) + if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI_Comm error' + if (stop_id /= 0 .and. worldsize > 1) call MPI_Abort(MPI_COMM_WORLD,1,err_MPI) + stop 1 ! error (message from IO_error) + endif end subroutine quit diff --git a/src/results.f90 b/src/result.f90 similarity index 69% rename from src/results.f90 rename to src/result.f90 index 8cdc82c28..0f29e9e53 100644 --- a/src/results.f90 +++ b/src/result.f90 @@ -4,8 +4,9 @@ !> @author Jennifer Nastola, Max-Planck-Institut für Eisenforschung GmbH !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !-------------------------------------------------------------------------------------------------- -module results +module result use prec + use misc use parallelization use IO use HDF5_utilities @@ -28,46 +29,46 @@ module results #endif private - integer(HID_T) :: resultsFile + integer(HID_T) :: resultFile - interface results_writeDataset - module procedure results_writeTensorDataset_real - module procedure results_writeVectorDataset_real - module procedure results_writeScalarDataset_real + interface result_writeDataset + module procedure result_writeTensorDataset_real + module procedure result_writeVectorDataset_real + module procedure result_writeScalarDataset_real - module procedure results_writeTensorDataset_int - module procedure results_writeVectorDataset_int - end interface results_writeDataset + module procedure result_writeTensorDataset_int + module procedure result_writeVectorDataset_int + end interface result_writeDataset - interface results_addAttribute - module procedure results_addAttribute_str - module procedure results_addAttribute_int - module procedure results_addAttribute_real + interface result_addAttribute + module procedure result_addAttribute_str + module procedure result_addAttribute_int + module procedure result_addAttribute_real - module procedure results_addAttribute_str_array - module procedure results_addAttribute_int_array - module procedure results_addAttribute_real_array - end interface results_addAttribute + module procedure result_addAttribute_str_array + module procedure result_addAttribute_int_array + module procedure result_addAttribute_real_array + end interface result_addAttribute public :: & - results_init, & - results_openJobFile, & - results_closeJobFile, & - results_addIncrement, & - results_finalizeIncrement, & - results_addGroup, & - results_openGroup, & - results_closeGroup, & - results_writeDataset, & - results_writeDataset_str, & - results_setLink, & - results_addAttribute, & - results_removeLink, & - results_mapping_phase, & - results_mapping_homogenization + result_init, & + result_openJobFile, & + result_closeJobFile, & + result_addIncrement, & + result_finalizeIncrement, & + result_addGroup, & + result_openGroup, & + result_closeGroup, & + result_writeDataset, & + result_writeDataset_str, & + result_setLink, & + result_addAttribute, & + result_removeLink, & + result_mapping_phase, & + result_mapping_homogenization contains -subroutine results_init(restart) +subroutine result_init(restart) logical, intent(in) :: restart @@ -76,68 +77,68 @@ subroutine results_init(restart) character(len=:), allocatable :: date - print'(/,1x,a)', '<<<+- results init -+>>>'; flush(IO_STDOUT) + print'(/,1x,a)', '<<<+- result init -+>>>'; flush(IO_STDOUT) print'(/,1x,a)', 'M. Diehl et al., Integrating Materials and Manufacturing Innovation 6(1):83–91, 2017' print'( 1x,a)', 'https://doi.org/10.1007/s40192-017-0084-5' if (.not. restart) then - resultsFile = HDF5_openFile(getSolverJobName()//'.hdf5','w') - call results_addAttribute('DADF5_version_major',0) - call results_addAttribute('DADF5_version_minor',14) + resultFile = HDF5_openFile(getSolverJobName()//'.hdf5','w') + call result_addAttribute('DADF5_version_major',1) + call result_addAttribute('DADF5_version_minor',0) call get_command_argument(0,commandLine) - call results_addAttribute('creator',trim(commandLine)//' '//DAMASKVERSION) - call results_addAttribute('created',now()) + call result_addAttribute('creator',trim(commandLine)//' '//DAMASKVERSION) + call result_addAttribute('created',now()) call get_command(commandLine) - call results_addAttribute('call',trim(commandLine)) - call results_closeGroup(results_addGroup('cell_to')) - call results_addAttribute('description','mappings to place data in space','cell_to') - call results_closeGroup(results_addGroup('setup')) - call results_addAttribute('description','input data used to run the simulation','setup') + call result_addAttribute('call',trim(commandLine)) + call result_closeGroup(result_addGroup('cell_to')) + call result_addAttribute('description','mappings to place data in space','cell_to') + call result_closeGroup(result_addGroup('setup')) + call result_addAttribute('description','input data used to run the simulation','setup') else date = now() - call results_openJobFile + call result_openJobFile() call get_command(commandLine) - call results_addAttribute('call (restart at '//date//')',trim(commandLine)) - call H5Gmove_f(resultsFile,'setup','tmp',hdferr) - call results_addAttribute('description','input data used to run the simulation up to restart at '//date,'tmp') - call results_closeGroup(results_addGroup('setup')) - call results_addAttribute('description','input data used to run the simulation','setup') - call H5Gmove_f(resultsFile,'tmp','setup/previous',hdferr) + call result_addAttribute('call (restart at '//date//')',trim(commandLine)) + call H5Gmove_f(resultFile,'setup','tmp',hdferr) + call result_addAttribute('description','input data used to run the simulation up to restart at '//date,'tmp') + call result_closeGroup(result_addGroup('setup')) + call result_addAttribute('description','input data used to run the simulation','setup') + call H5Gmove_f(resultFile,'tmp','setup/previous',hdferr) end if - call results_closeJobFile + call result_closeJobFile() -end subroutine results_init +end subroutine result_init !-------------------------------------------------------------------------------------------------- -!> @brief opens the results file to append data +!> @brief opens the result file to append data !-------------------------------------------------------------------------------------------------- -subroutine results_openJobFile(parallel) +subroutine result_openJobFile(parallel) logical, intent(in), optional :: parallel - resultsFile = HDF5_openFile(getSolverJobName()//'.hdf5','a',parallel) + resultFile = HDF5_openFile(getSolverJobName()//'.hdf5','a',parallel) -end subroutine results_openJobFile +end subroutine result_openJobFile !-------------------------------------------------------------------------------------------------- -!> @brief closes the results file +!> @brief closes the result file !-------------------------------------------------------------------------------------------------- -subroutine results_closeJobFile +subroutine result_closeJobFile - call HDF5_closeFile(resultsFile) + call HDF5_closeFile(resultFile) -end subroutine results_closeJobFile +end subroutine result_closeJobFile !-------------------------------------------------------------------------------------------------- !> @brief creates the group of increment and adds time as attribute to the file !-------------------------------------------------------------------------------------------------- -subroutine results_addIncrement(inc,time) +subroutine result_addIncrement(inc,time) integer, intent(in) :: inc real(pReal), intent(in) :: time @@ -146,225 +147,201 @@ subroutine results_addIncrement(inc,time) write(incChar,'(i10)') inc - call results_closeGroup(results_addGroup(trim('increment_'//trim(adjustl(incChar))))) - call results_setLink(trim('increment_'//trim(adjustl(incChar))),'current') - call results_addAttribute('t/s',time,trim('increment_'//trim(adjustl(incChar)))) + call result_closeGroup(result_addGroup(trim('increment_'//trim(adjustl(incChar))))) + call result_setLink(trim('increment_'//trim(adjustl(incChar))),'current') + call result_addAttribute('t/s',time,trim('increment_'//trim(adjustl(incChar)))) -end subroutine results_addIncrement +end subroutine result_addIncrement !-------------------------------------------------------------------------------------------------- !> @brief finalize increment !> @details remove soft link !-------------------------------------------------------------------------------------------------- -subroutine results_finalizeIncrement +subroutine result_finalizeIncrement - call results_removeLink('current') + call result_removeLink('current') -end subroutine results_finalizeIncrement +end subroutine result_finalizeIncrement !-------------------------------------------------------------------------------------------------- -!> @brief open a group from the results file +!> @brief open a group from the result file !-------------------------------------------------------------------------------------------------- -integer(HID_T) function results_openGroup(groupName) +integer(HID_T) function result_openGroup(groupName) character(len=*), intent(in) :: groupName - results_openGroup = HDF5_openGroup(resultsFile,groupName) + result_openGroup = HDF5_openGroup(resultFile,groupName) -end function results_openGroup +end function result_openGroup !-------------------------------------------------------------------------------------------------- -!> @brief adds a new group to the results file +!> @brief adds a new group to the result file !-------------------------------------------------------------------------------------------------- -integer(HID_T) function results_addGroup(groupName) +integer(HID_T) function result_addGroup(groupName) character(len=*), intent(in) :: groupName - results_addGroup = HDF5_addGroup(resultsFile,groupName) + result_addGroup = HDF5_addGroup(resultFile,groupName) -end function results_addGroup +end function result_addGroup !-------------------------------------------------------------------------------------------------- !> @brief close a group !-------------------------------------------------------------------------------------------------- -subroutine results_closeGroup(group_id) +subroutine result_closeGroup(group_id) integer(HID_T), intent(in) :: group_id call HDF5_closeGroup(group_id) -end subroutine results_closeGroup +end subroutine result_closeGroup !-------------------------------------------------------------------------------------------------- -!> @brief set link to object in results file +!> @brief set link to object in result file !-------------------------------------------------------------------------------------------------- -subroutine results_setLink(path,link) +subroutine result_setLink(path,link) character(len=*), intent(in) :: path, link - call HDF5_setLink(resultsFile,path,link) + call HDF5_setLink(resultFile,path,link) -end subroutine results_setLink +end subroutine result_setLink !-------------------------------------------------------------------------------------------------- -!> @brief Add a string attribute to an object in the results file. +!> @brief Add a string attribute to an object in the result file. !-------------------------------------------------------------------------------------------------- -subroutine results_addAttribute_str(attrLabel,attrValue,path) +subroutine result_addAttribute_str(attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel, attrValue character(len=*), intent(in), optional :: path - if (present(path)) then - call HDF5_addAttribute(resultsFile,attrLabel, attrValue, path) - else - call HDF5_addAttribute(resultsFile,attrLabel, attrValue) - end if + call HDF5_addAttribute(resultFile,attrLabel, attrValue, path) -end subroutine results_addAttribute_str +end subroutine result_addAttribute_str !-------------------------------------------------------------------------------------------------- -!> @brief Add an integer attribute an object in the results file. +!> @brief Add an integer attribute to an object in the result file. !-------------------------------------------------------------------------------------------------- -subroutine results_addAttribute_int(attrLabel,attrValue,path) +subroutine result_addAttribute_int(attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel integer, intent(in) :: attrValue character(len=*), intent(in), optional :: path - if (present(path)) then - call HDF5_addAttribute(resultsFile,attrLabel, attrValue, path) - else - call HDF5_addAttribute(resultsFile,attrLabel, attrValue) - end if + call HDF5_addAttribute(resultFile,attrLabel, attrValue, path) -end subroutine results_addAttribute_int +end subroutine result_addAttribute_int !-------------------------------------------------------------------------------------------------- -!> @brief Add a real attribute an object in the results file. +!> @brief Add a real (float) attribute to an object in the result file. !-------------------------------------------------------------------------------------------------- -subroutine results_addAttribute_real(attrLabel,attrValue,path) +subroutine result_addAttribute_real(attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel real(pReal), intent(in) :: attrValue character(len=*), intent(in), optional :: path - if (present(path)) then - call HDF5_addAttribute(resultsFile,attrLabel, attrValue, path) - else - call HDF5_addAttribute(resultsFile,attrLabel, attrValue) - end if + call HDF5_addAttribute(resultFile,attrLabel, attrValue, path) -end subroutine results_addAttribute_real +end subroutine result_addAttribute_real !-------------------------------------------------------------------------------------------------- -!> @brief Add a string array attribute an object in the results file. +!> @brief Add a string array attribute to an object in the result file. !-------------------------------------------------------------------------------------------------- -subroutine results_addAttribute_str_array(attrLabel,attrValue,path) +subroutine result_addAttribute_str_array(attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel character(len=*), intent(in), dimension(:) :: attrValue character(len=*), intent(in), optional :: path - if (present(path)) then - call HDF5_addAttribute(resultsFile,attrLabel, attrValue, path) - else - call HDF5_addAttribute(resultsFile,attrLabel, attrValue) - end if + call HDF5_addAttribute(resultFile,attrLabel, attrValue, path) -end subroutine results_addAttribute_str_array +end subroutine result_addAttribute_str_array !-------------------------------------------------------------------------------------------------- -!> @brief Add an integer array attribute an object in the results file. +!> @brief Add an integer array attribute to an object in the result file. !-------------------------------------------------------------------------------------------------- -subroutine results_addAttribute_int_array(attrLabel,attrValue,path) +subroutine result_addAttribute_int_array(attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel integer, intent(in), dimension(:) :: attrValue character(len=*), intent(in), optional :: path - if (present(path)) then - call HDF5_addAttribute(resultsFile,attrLabel, attrValue, path) - else - call HDF5_addAttribute(resultsFile,attrLabel, attrValue) - end if + call HDF5_addAttribute(resultFile,attrLabel, attrValue, path) -end subroutine results_addAttribute_int_array +end subroutine result_addAttribute_int_array !-------------------------------------------------------------------------------------------------- -!> @brief Add a real array attribute an object in the results file. +!> @brief Add a real (float) array attribute to an object in the result file. !-------------------------------------------------------------------------------------------------- -subroutine results_addAttribute_real_array(attrLabel,attrValue,path) +subroutine result_addAttribute_real_array(attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel real(pReal), intent(in), dimension(:) :: attrValue character(len=*), intent(in), optional :: path - if (present(path)) then - call HDF5_addAttribute(resultsFile,attrLabel, attrValue, path) - else - call HDF5_addAttribute(resultsFile,attrLabel, attrValue) - end if + call HDF5_addAttribute(resultFile,attrLabel, attrValue, path) -end subroutine results_addAttribute_real_array +end subroutine result_addAttribute_real_array !-------------------------------------------------------------------------------------------------- !> @brief remove link to an object !-------------------------------------------------------------------------------------------------- -subroutine results_removeLink(link) +subroutine result_removeLink(link) character(len=*), intent(in) :: link integer :: hdferr - call H5Ldelete_f(resultsFile,link, hdferr) - if (hdferr < 0) call IO_error(1,ext_msg = 'results_removeLink: H5Ldelete_soft_f ('//trim(link)//')') + call H5Ldelete_f(resultFile,link, hdferr) + if (hdferr < 0) call IO_error(1,ext_msg = 'result_removeLink: H5Ldelete_soft_f ('//trim(link)//')') -end subroutine results_removeLink +end subroutine result_removeLink !-------------------------------------------------------------------------------------------------- !> @brief Store string dataset. !> @details Not collective, must be called by one process at at time. !-------------------------------------------------------------------------------------------------- -subroutine results_writeDataset_str(dataset,group,label,description) +subroutine result_writeDataset_str(dataset,group,label,description) character(len=*), intent(in) :: label,group,description,dataset integer(HID_T) :: groupHandle - groupHandle = results_openGroup(group) + groupHandle = result_openGroup(group) call HDF5_write_str(dataset,groupHandle,label) call executionStamp(group//'/'//label,description) call HDF5_closeGroup(groupHandle) -end subroutine results_writeDataset_str +end subroutine result_writeDataset_str !-------------------------------------------------------------------------------------------------- !> @brief Store real scalar dataset with associated metadata. !-------------------------------------------------------------------------------------------------- -subroutine results_writeScalarDataset_real(dataset,group,label,description,SIunit) +subroutine result_writeScalarDataset_real(dataset,group,label,description,SIunit) character(len=*), intent(in) :: label,group,description character(len=*), intent(in), optional :: SIunit @@ -373,18 +350,18 @@ subroutine results_writeScalarDataset_real(dataset,group,label,description,SIuni integer(HID_T) :: groupHandle - groupHandle = results_openGroup(group) + groupHandle = result_openGroup(group) call HDF5_write(dataset,groupHandle,label) call executionStamp(group//'/'//label,description,SIunit) call HDF5_closeGroup(groupHandle) -end subroutine results_writeScalarDataset_real +end subroutine result_writeScalarDataset_real !-------------------------------------------------------------------------------------------------- !> @brief Store real vector dataset with associated metadata. !-------------------------------------------------------------------------------------------------- -subroutine results_writeVectorDataset_real(dataset,group,label,description,SIunit,systems) +subroutine result_writeVectorDataset_real(dataset,group,label,description,SIunit,systems) character(len=*), intent(in) :: label,group,description character(len=*), intent(in), optional :: SIunit @@ -394,21 +371,21 @@ subroutine results_writeVectorDataset_real(dataset,group,label,description,SIuni integer(HID_T) :: groupHandle - groupHandle = results_openGroup(group) + groupHandle = result_openGroup(group) call HDF5_write(dataset,groupHandle,label) call executionStamp(group//'/'//label,description,SIunit) if (present(systems) .and. HDF5_objectExists(groupHandle,label)) & - call HDF5_addAttribute(resultsFile,'systems',systems,group//'/'//label) + call HDF5_addAttribute(resultFile,'systems',systems,group//'/'//label) call HDF5_closeGroup(groupHandle) -end subroutine results_writeVectorDataset_real +end subroutine result_writeVectorDataset_real !-------------------------------------------------------------------------------------------------- !> @brief Store real tensor dataset with associated metadata. !> @details Data is transposed to compenstate transposed storage order. !-------------------------------------------------------------------------------------------------- -subroutine results_writeTensorDataset_real(dataset,group,label,description,SIunit,transposed) +subroutine result_writeTensorDataset_real(dataset,group,label,description,SIunit,transposed) character(len=*), intent(in) :: label,group,description character(len=*), intent(in), optional :: SIunit @@ -416,19 +393,12 @@ subroutine results_writeTensorDataset_real(dataset,group,label,description,SIuni real(pReal), intent(in), dimension(:,:,:) :: dataset integer :: i - logical :: transposed_ integer(HID_T) :: groupHandle real(pReal), dimension(:,:,:), allocatable :: dataset_transposed - if (present(transposed)) then - transposed_ = transposed - else - transposed_ = .true. - end if - - groupHandle = results_openGroup(group) - if (transposed_) then + groupHandle = result_openGroup(group) + if (misc_optional(transposed,.true.)) then if (size(dataset,1) /= size(dataset,2)) error stop 'transpose non-symmetric tensor' allocate(dataset_transposed,mold=dataset) do i=1,size(dataset_transposed,3) @@ -441,13 +411,13 @@ subroutine results_writeTensorDataset_real(dataset,group,label,description,SIuni call executionStamp(group//'/'//label,description,SIunit) call HDF5_closeGroup(groupHandle) -end subroutine results_writeTensorDataset_real +end subroutine result_writeTensorDataset_real !-------------------------------------------------------------------------------------------------- !> @brief Store integer vector dataset with associated metadata. !-------------------------------------------------------------------------------------------------- -subroutine results_writeVectorDataset_int(dataset,group,label,description,SIunit,systems) +subroutine result_writeVectorDataset_int(dataset,group,label,description,SIunit,systems) character(len=*), intent(in) :: label,group,description character(len=*), intent(in), optional :: SIunit @@ -457,20 +427,20 @@ subroutine results_writeVectorDataset_int(dataset,group,label,description,SIunit integer(HID_T) :: groupHandle - groupHandle = results_openGroup(group) + groupHandle = result_openGroup(group) call HDF5_write(dataset,groupHandle,label) call executionStamp(group//'/'//label,description,SIunit) if (present(systems) .and. HDF5_objectExists(groupHandle,label)) & - call HDF5_addAttribute(resultsFile,'systems',systems,group//'/'//label) + call HDF5_addAttribute(resultFile,'systems',systems,group//'/'//label) call HDF5_closeGroup(groupHandle) -end subroutine results_writeVectorDataset_int +end subroutine result_writeVectorDataset_int !-------------------------------------------------------------------------------------------------- !> @brief Store integer tensor dataset with associated metadata. !-------------------------------------------------------------------------------------------------- -subroutine results_writeTensorDataset_int(dataset,group,label,description,SIunit) +subroutine result_writeTensorDataset_int(dataset,group,label,description,SIunit) character(len=*), intent(in) :: label,group,description character(len=*), intent(in), optional :: SIunit @@ -479,19 +449,19 @@ subroutine results_writeTensorDataset_int(dataset,group,label,description,SIunit integer(HID_T) :: groupHandle - groupHandle = results_openGroup(group) + groupHandle = result_openGroup(group) call HDF5_write(dataset,groupHandle,label) call executionStamp(group//'/'//label,description,SIunit) call HDF5_closeGroup(groupHandle) -end subroutine results_writeTensorDataset_int +end subroutine result_writeTensorDataset_int !-------------------------------------------------------------------------------------------------- !> @brief adds the unique mapping from spatial position and constituent ID to results !-------------------------------------------------------------------------------------------------- -subroutine results_mapping_phase(ID,entry,label) +subroutine result_mapping_phase(ID,entry,label) integer, dimension(:,:), intent(in) :: ID !< phase ID at (co,ce) integer, dimension(:,:), intent(in) :: entry !< phase entry at (co,ce) @@ -527,7 +497,7 @@ subroutine results_mapping_phase(ID,entry,label) writeSize(worldrank) = size(entry(1,:)) ! total number of entries of this process call H5Pcreate_f(H5P_DATASET_XFER_F, plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #ifndef PETSC entryGlobal = int(entry -1,pI64) ! 0-based @@ -535,10 +505,10 @@ subroutine results_mapping_phase(ID,entry,label) !-------------------------------------------------------------------------------------------------- ! MPI settings and communication call H5Pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call MPI_Allreduce(MPI_IN_PLACE,writeSize,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI) ! get output at each process - if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' + call parallelization_chkerr(err_MPI) entryOffset = 0_pI64 do co = 1, size(ID,1) @@ -547,7 +517,7 @@ subroutine results_mapping_phase(ID,entry,label) end do end do call MPI_Allreduce(MPI_IN_PLACE,entryOffset,size(entryOffset),MPI_INTEGER8,MPI_SUM,MPI_COMM_WORLD,err_MPI)! get offset at each process - if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' + call parallelization_chkerr(err_MPI) entryOffset(:,worldrank) = sum(entryOffset(:,0:worldrank-1),2) do co = 1, size(ID,1) do ce = 1, size(ID,2) @@ -563,91 +533,91 @@ subroutine results_mapping_phase(ID,entry,label) !--------------------------------------------------------------------------------------------------- ! compound type: label(ID) + entry call H5Tcopy_f(H5T_NATIVE_CHARACTER, dt_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tset_size_f(dt_id, int(len(label(1)),SIZE_T), hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tget_size_f(dt_id, type_size_string, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) pI64_t = h5kind_to_type(kind(entryGlobal),H5_INTEGER_KIND) call H5Tget_size_f(pI64_t, type_size_int, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tcreate_f(H5T_COMPOUND_F, type_size_string + type_size_int, dtype_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tinsert_f(dtype_id, 'label', 0_SIZE_T, dt_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tinsert_f(dtype_id, 'entry', type_size_string, pI64_t, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! create memory types for each component of the compound type call H5Tcreate_f(H5T_COMPOUND_F, type_size_string, label_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tinsert_f(label_id, 'label', 0_SIZE_T, dt_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tcreate_f(H5T_COMPOUND_F, type_size_int, entry_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tinsert_f(entry_id, 'entry', 0_SIZE_T, pI64_t, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(dt_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! create dataspace in memory (local shape = hyperslab) and in file (global shape) call H5Screate_simple_f(2,myShape,memspace_id,hdferr,myShape) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Screate_simple_f(2,totalShape,filespace_id,hdferr,totalShape) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sselect_hyperslab_f(filespace_id, H5S_SELECT_SET_F, myOffset, myShape, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! write the components of the compound type individually call H5Pset_preserve_f(plist_id, .true., hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) - loc_id = results_openGroup('/cell_to') + loc_id = result_openGroup('/cell_to') call H5Dcreate_f(loc_id, 'phase', dtype_id, filespace_id, dset_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dwrite_f(dset_id, label_id, reshape(label(pack(ID,.true.)),myShape), & myShape, hdferr, file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dwrite_f(dset_id, entry_id, reshape(pack(entryGlobal,.true.),myShape), & myShape, hdferr, file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! close all call HDF5_closeGroup(loc_id) call H5Pclose_f(plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(filespace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(memspace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dclose_f(dset_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(dtype_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(label_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(entry_id, hdferr) call executionStamp('cell_to/phase','cell ID and constituent ID to phase results') -end subroutine results_mapping_phase +end subroutine result_mapping_phase !-------------------------------------------------------------------------------------------------- !> @brief adds the unique mapping from spatial position and constituent ID to results !-------------------------------------------------------------------------------------------------- -subroutine results_mapping_homogenization(ID,entry,label) +subroutine result_mapping_homogenization(ID,entry,label) integer, dimension(:), intent(in) :: ID !< homogenization ID at (ce) integer, dimension(:), intent(in) :: entry !< homogenization entry at (ce) @@ -683,7 +653,7 @@ subroutine results_mapping_homogenization(ID,entry,label) writeSize(worldrank) = size(entry) ! total number of entries of this process call H5Pcreate_f(H5P_DATASET_XFER_F, plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) #ifndef PETSC entryGlobal = int(entry -1,pI64) ! 0-based @@ -691,17 +661,17 @@ subroutine results_mapping_homogenization(ID,entry,label) !-------------------------------------------------------------------------------------------------- ! MPI settings and communication call H5Pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call MPI_Allreduce(MPI_IN_PLACE,writeSize,worldsize,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,err_MPI) ! get output at each process - if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' + call parallelization_chkerr(err_MPI) entryOffset = 0_pI64 do ce = 1, size(ID,1) entryOffset(ID(ce),worldrank) = entryOffset(ID(ce),worldrank) +1_pI64 end do call MPI_Allreduce(MPI_IN_PLACE,entryOffset,size(entryOffset),MPI_INTEGER8,MPI_SUM,MPI_COMM_WORLD,err_MPI)! get offset at each process - if (err_MPI /= 0_MPI_INTEGER_KIND) error stop 'MPI error' + call parallelization_chkerr(err_MPI) entryOffset(:,worldrank) = sum(entryOffset(:,0:worldrank-1),2) do ce = 1, size(ID,1) entryGlobal(ce) = int(entry(ce),pI64) -1_pI64 + entryOffset(ID(ce),worldrank) @@ -715,86 +685,86 @@ subroutine results_mapping_homogenization(ID,entry,label) !--------------------------------------------------------------------------------------------------- ! compound type: label(ID) + entry call H5Tcopy_f(H5T_NATIVE_CHARACTER, dt_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tset_size_f(dt_id, int(len(label(1)),SIZE_T), hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tget_size_f(dt_id, type_size_string, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) pI64_t = h5kind_to_type(kind(entryGlobal),H5_INTEGER_KIND) call H5Tget_size_f(pI64_t, type_size_int, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tcreate_f(H5T_COMPOUND_F, type_size_string + type_size_int, dtype_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tinsert_f(dtype_id, 'label', 0_SIZE_T, dt_id,hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tinsert_f(dtype_id, 'entry', type_size_string, pI64_t, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! create memory types for each component of the compound type call H5Tcreate_f(H5T_COMPOUND_F, type_size_string, label_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tinsert_f(label_id, 'label', 0_SIZE_T, dt_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tcreate_f(H5T_COMPOUND_F, type_size_int, entry_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tinsert_f(entry_id, 'entry', 0_SIZE_T, pI64_t, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(dt_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! create dataspace in memory (local shape = hyperslab) and in file (global shape) call H5Screate_simple_f(1,myShape,memspace_id,hdferr,myShape) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Screate_simple_f(1,totalShape,filespace_id,hdferr,totalShape) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sselect_hyperslab_f(filespace_id, H5S_SELECT_SET_F, myOffset, myShape, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! write the components of the compound type individually call H5Pset_preserve_f(plist_id, .true., hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) - loc_id = results_openGroup('/cell_to') + loc_id = result_openGroup('/cell_to') call H5Dcreate_f(loc_id, 'homogenization', dtype_id, filespace_id, dset_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dwrite_f(dset_id, label_id, reshape(label(pack(ID,.true.)),myShape), & myShape, hdferr, file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dwrite_f(dset_id, entry_id, reshape(pack(entryGlobal,.true.),myShape), & myShape, hdferr, file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) !-------------------------------------------------------------------------------------------------- ! close all call HDF5_closeGroup(loc_id) call H5Pclose_f(plist_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(filespace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Sclose_f(memspace_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Dclose_f(dset_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(dtype_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(label_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call H5Tclose_f(entry_id, hdferr) - if (hdferr < 0) error stop 'HDF5 error' + call HDF5_chkerr(hdferr) call executionStamp('cell_to/homogenization','cell ID to homogenization results') -end subroutine results_mapping_homogenization +end subroutine result_mapping_homogenization !-------------------------------------------------------------------------------------------------- @@ -806,14 +776,14 @@ subroutine executionStamp(path,description,SIunit) character(len=*), intent(in), optional :: SIunit - if (HDF5_objectExists(resultsFile,path)) & - call HDF5_addAttribute(resultsFile,'creator','DAMASK '//DAMASKVERSION,path) - if (HDF5_objectExists(resultsFile,path)) & - call HDF5_addAttribute(resultsFile,'created',now(),path) - if (HDF5_objectExists(resultsFile,path)) & - call HDF5_addAttribute(resultsFile,'description',description,path) - if (HDF5_objectExists(resultsFile,path) .and. present(SIunit)) & - call HDF5_addAttribute(resultsFile,'unit',SIunit,path) + if (HDF5_objectExists(resultFile,path)) & + call HDF5_addAttribute(resultFile,'creator','DAMASK '//DAMASKVERSION,path) + if (HDF5_objectExists(resultFile,path)) & + call HDF5_addAttribute(resultFile,'created',now(),path) + if (HDF5_objectExists(resultFile,path)) & + call HDF5_addAttribute(resultFile,'description',description,path) + if (HDF5_objectExists(resultFile,path) .and. present(SIunit)) & + call HDF5_addAttribute(resultFile,'unit',SIunit,path) end subroutine executionStamp @@ -834,4 +804,4 @@ character(len=24) function now() end function now -end module results +end module result diff --git a/src/rotations.f90 b/src/rotations.f90 index 657480ef4..35fb30026 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -106,7 +106,7 @@ subroutine rotations_init print'(/,1x,a)', 'D. Rowenhorst et al., Modelling and Simulation in Materials Science and Engineering 23:083501, 2015' print'( 1x,a)', 'https://doi.org/10.1088/0965-0393/23/8/083501' - call selfTest + call selfTest() end subroutine rotations_init @@ -178,11 +178,7 @@ subroutine fromEulers(self,eu,degrees) real(pReal), dimension(3) :: Eulers - if (.not. present(degrees)) then - Eulers = eu - else - Eulers = merge(eu*INRAD,eu,degrees) - end if + Eulers = merge(eu*INRAD,eu,misc_optional(degrees,.false.)) if (any(Eulers<0.0_pReal) .or. any(Eulers>TAU) .or. Eulers(2) > PI) & call IO_error(402,ext_msg='fromEulers') @@ -202,18 +198,10 @@ subroutine fromAxisAngle(self,ax,degrees,P) real(pReal),dimension(3) :: axis - if (.not. present(degrees)) then - angle = ax(4) - else - angle = merge(ax(4)*INRAD,ax(4),degrees) - end if + angle = merge(ax(4)*INRAD,ax(4),misc_optional(degrees,.false.)) - if (.not. present(P)) then - axis = ax(1:3) - else - axis = ax(1:3) * merge(-1.0_pReal,1.0_pReal,P == 1) - if (abs(P) /= 1) call IO_error(402,ext_msg='fromAxisAngle (P)') - end if + axis = ax(1:3) * merge(-1.0_pReal,1.0_pReal,misc_optional(P,-1) == 1) + if (abs(misc_optional(P,-1)) /= 1) call IO_error(402,ext_msg='fromAxisAngle (P)') if (dNeq(norm2(axis),1.0_pReal) .or. angle < 0.0_pReal .or. angle > PI) & call IO_error(402,ext_msg='fromAxisAngle') @@ -277,22 +265,15 @@ pure function rotVector(self,v,active) result(vRot) logical, intent(in), optional :: active real(pReal), dimension(4) :: v_normed, q - logical :: passive - if (present(active)) then - passive = .not. active - else - passive = .true. - end if - if (dEq0(norm2(v))) then vRot = v else v_normed = [0.0_pReal,v]/norm2(v) - q = merge(multiplyQuaternion(self%q, multiplyQuaternion(v_normed, conjugateQuaternion(self%q))), & - multiplyQuaternion(conjugateQuaternion(self%q), multiplyQuaternion(v_normed, self%q)), & - passive) + q = merge(multiplyQuaternion(conjugateQuaternion(self%q), multiplyQuaternion(v_normed, self%q)), & + multiplyQuaternion(self%q, multiplyQuaternion(v_normed, conjugateQuaternion(self%q))), & + misc_optional(active,.false.)) vRot = q(2:4)*norm2(v) end if @@ -311,18 +292,10 @@ pure function rotTensor2(self,T,active) result(tRot) real(pReal), intent(in), dimension(3,3) :: T logical, intent(in), optional :: active - logical :: passive - - if (present(active)) then - passive = .not. active - else - passive = .true. - end if - - tRot = merge(matmul(matmul(self%asMatrix(),T),transpose(self%asMatrix())), & - matmul(matmul(transpose(self%asMatrix()),T),self%asMatrix()), & - passive) + tRot = merge(matmul(matmul(transpose(self%asMatrix()),T),self%asMatrix()), & + matmul(matmul(self%asMatrix(),T),transpose(self%asMatrix())), & + misc_optional(active,.false.)) end function rotTensor2 @@ -342,12 +315,7 @@ pure function rotTensor4(self,T,active) result(tRot) real(pReal), dimension(3,3) :: R integer :: i,j,k,l,m,n,o,p - - if (present(active)) then - R = merge(transpose(self%asMatrix()),self%asMatrix(),active) - else - R = self%asMatrix() - end if + R = merge(transpose(self%asMatrix()),self%asMatrix(),misc_optional(active,.false.)) tRot = 0.0_pReal do i = 1,3;do j = 1,3;do k = 1,3;do l = 1,3 @@ -375,11 +343,7 @@ pure function rotStiffness(self,C,active) result(cRot) real(pReal), dimension(6,6) :: M - if (present(active)) then - R = merge(transpose(self%asMatrix()),self%asMatrix(),active) - else - R = self%asMatrix() - end if + R = merge(transpose(self%asMatrix()),self%asMatrix(),misc_optional(active,.false.)) M = reshape([R(1,1)**2, R(2,1)**2, R(3,1)**2, & R(2,1)*R(3,1), R(1,1)*R(3,1), R(1,1)*R(2,1), & diff --git a/src/signals.f90 b/src/signal.f90 similarity index 60% rename from src/signals.f90 rename to src/signal.f90 index 3f0397d3d..4513fc0b2 100644 --- a/src/signals.f90 +++ b/src/signal.f90 @@ -2,7 +2,7 @@ !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief Handling of UNIX signals. !-------------------------------------------------------------------------------------------------- -module signals +module signal use prec use system_routines @@ -10,15 +10,15 @@ module signals private logical, volatile, public, protected :: & - signals_SIGINT = .false., & !< interrupt signal - signals_SIGUSR1 = .false., & !< 1. user-defined signal - signals_SIGUSR2 = .false. !< 2. user-defined signal + signal_SIGINT = .false., & !< interrupt signal + signal_SIGUSR1 = .false., & !< 1. user-defined signal + signal_SIGUSR2 = .false. !< 2. user-defined signal public :: & - signals_init, & - signals_setSIGINT, & - signals_setSIGUSR1, & - signals_setSIGUSR2 + signal_init, & + signal_setSIGINT, & + signal_setSIGUSR1, & + signal_setSIGUSR2 contains @@ -26,100 +26,100 @@ contains !-------------------------------------------------------------------------------------------------- !> @brief Register signal handlers. !-------------------------------------------------------------------------------------------------- -subroutine signals_init() +subroutine signal_init() call signalint_c(c_funloc(catchSIGINT)) call signalusr1_c(c_funloc(catchSIGUSR1)) call signalusr2_c(c_funloc(catchSIGUSR2)) -end subroutine signals_init +end subroutine signal_init !-------------------------------------------------------------------------------------------------- -!> @brief Set global variable signals_SIGINT to .true. -!> @details This function can be registered to catch signals send to the executable. +!> @brief Set global variable signal_SIGINT to .true. +!> @details This function can be registered to catch signals sent to the executable. !-------------------------------------------------------------------------------------------------- -subroutine catchSIGINT(signal) bind(C) +subroutine catchSIGINT(sig) bind(C) - integer(C_INT), value :: signal + integer(C_INT), value :: sig - print'(a,i0)', ' received signal ',signal - call signals_setSIGINT(.true.) + print'(a,i0)', ' received signal ',sig + call signal_setSIGINT(.true.) end subroutine catchSIGINT !-------------------------------------------------------------------------------------------------- -!> @brief Set global variable signals_SIGUSR1 to .true. -!> @details This function can be registered to catch signals send to the executable. +!> @brief Set global variable signal_SIGUSR1 to .true. +!> @details This function can be registered to catch signals sent to the executable. !-------------------------------------------------------------------------------------------------- -subroutine catchSIGUSR1(signal) bind(C) +subroutine catchSIGUSR1(sig) bind(C) - integer(C_INT), value :: signal + integer(C_INT), value :: sig - print'(a,i0)', ' received signal ',signal - call signals_setSIGUSR1(.true.) + print'(a,i0)', ' received signal ',sig + call signal_setSIGUSR1(.true.) end subroutine catchSIGUSR1 !-------------------------------------------------------------------------------------------------- -!> @brief Set global variable signals_SIGUSR2 to .true. -!> @details This function can be registered to catch signals send to the executable. +!> @brief Set global variable signal_SIGUSR2 to .true. +!> @details This function can be registered to catch signals sent to the executable. !-------------------------------------------------------------------------------------------------- -subroutine catchSIGUSR2(signal) bind(C) +subroutine catchSIGUSR2(sig) bind(C) - integer(C_INT), value :: signal + integer(C_INT), value :: sig - print'(a,i0,a)', ' received signal ',signal - call signals_setSIGUSR2(.true.) + print'(a,i0,a)', ' received signal ',sig + call signal_setSIGUSR2(.true.) end subroutine catchSIGUSR2 !-------------------------------------------------------------------------------------------------- -!> @brief Set global variable signals_SIGINT. +!> @brief Set global variable signal_SIGINT. !-------------------------------------------------------------------------------------------------- -subroutine signals_setSIGINT(state) +subroutine signal_setSIGINT(state) logical, intent(in) :: state - signals_SIGINT = state + signal_SIGINT = state print*, 'set SIGINT to',state -end subroutine signals_setSIGINT +end subroutine signal_setSIGINT !-------------------------------------------------------------------------------------------------- -!> @brief Set global variable signals_SIGUSR. +!> @brief Set global variable signal_SIGUSR. !-------------------------------------------------------------------------------------------------- -subroutine signals_setSIGUSR1(state) +subroutine signal_setSIGUSR1(state) logical, intent(in) :: state - signals_SIGUSR1 = state + signal_SIGUSR1 = state print*, 'set SIGUSR1 to',state -end subroutine signals_setSIGUSR1 +end subroutine signal_setSIGUSR1 !-------------------------------------------------------------------------------------------------- -!> @brief Set global variable signals_SIGUSR2. +!> @brief Set global variable signal_SIGUSR2. !-------------------------------------------------------------------------------------------------- -subroutine signals_setSIGUSR2(state) +subroutine signal_setSIGUSR2(state) logical, intent(in) :: state - signals_SIGUSR2 = state + signal_SIGUSR2 = state print*, 'set SIGUSR2 to',state -end subroutine signals_setSIGUSR2 +end subroutine signal_setSIGUSR2 -end module signals +end module signal diff --git a/src/system_routines.f90 b/src/system_routines.f90 index 74aa4685b..0ac8eadd0 100644 --- a/src/system_routines.f90 +++ b/src/system_routines.f90 @@ -94,7 +94,7 @@ contains !-------------------------------------------------------------------------------------------------- -!> @brief set the current working directory +!> @brief Set the current working directory. !-------------------------------------------------------------------------------------------------- logical function setCWD(path) @@ -107,7 +107,7 @@ end function setCWD !-------------------------------------------------------------------------------------------------- -!> @brief get the current working directory +!> @brief Get the current working directory. !-------------------------------------------------------------------------------------------------- function getCWD() @@ -129,7 +129,7 @@ end function getCWD !-------------------------------------------------------------------------------------------------- -!> @brief get the host name +!> @brief Get the host name. !-------------------------------------------------------------------------------------------------- function getHostName() @@ -151,7 +151,7 @@ end function getHostName !-------------------------------------------------------------------------------------------------- -!> @brief get the user name +!> @brief Get the user name. !-------------------------------------------------------------------------------------------------- function getUserName() @@ -181,15 +181,15 @@ pure function c_f_string(c_string) result(f_string) character(kind=C_CHAR), dimension(:), intent(in) :: c_string character(len=:), allocatable :: f_string - integer :: i + integer(pI64) :: i - allocate(character(len=size(c_string))::f_string) - arrayToString: do i=1,len(f_string) + allocate(character(len=size(c_string,kind=pI64))::f_string) + arrayToString: do i=1_pI64,len(f_string,pI64) if (c_string(i) /= C_NULL_CHAR) then f_string(i:i)=c_string(i) else - f_string = f_string(:i-1) + f_string = f_string(:i-1_pI64) exit end if end do arrayToString @@ -203,11 +203,11 @@ end function c_f_string !-------------------------------------------------------------------------------------------------- pure function f_c_string(f_string) result(c_string) - character(len=*), intent(in) :: f_string - character(kind=C_CHAR), dimension(len_trim(f_string)+1) :: c_string + character(len=*), intent(in) :: f_string + character(kind=C_CHAR), dimension(len_trim(f_string,pI64)+1_pI64) :: c_string - c_string = transfer(trim(f_string)//C_NULL_CHAR,c_string,size=size(c_string)) + c_string = transfer(trim(f_string)//C_NULL_CHAR,c_string,size=size(c_string,kind=pI64)) end function f_c_string diff --git a/src/test/DAMASK_test.f90 b/src/test/DAMASK_test.f90 new file mode 100644 index 000000000..34c1dc88a --- /dev/null +++ b/src/test/DAMASK_test.f90 @@ -0,0 +1,15 @@ +program DAMASK_test + use parallelization + use HDF5_utilities + + use test_prec + use test_HDF5_utilities + + call prec_test() + + call parallelization_init() + call HDF5_utilities_init() + + call HDF5_utilities_test() + +end program DAMASK_test diff --git a/src/test/test_HDF5_utilities.f90 b/src/test/test_HDF5_utilities.f90 new file mode 100644 index 000000000..815bbe671 --- /dev/null +++ b/src/test/test_HDF5_utilities.f90 @@ -0,0 +1,39 @@ +module test_HDF5_utilities + use prec + use HDF5 + use HDF5_utilities + + implicit none(type,external) + + private + public :: HDF5_utilities_test + + contains + +subroutine HDF5_utilities_test() + + print*, 'begin test HDF5_utilities' + call test_read_write() + print*, 'end test HDF5_utilities' + +end subroutine HDF5_utilities_test + + +subroutine test_read_write() + + integer(HID_T) :: f + real(pReal), dimension(3) :: d_in,d_out + + + call random_number(d_in) + + f = HDF5_openFile('test.hdf5','w') + + call HDF5_write(d_in,f,'test') + call HDF5_read(d_out,f,'test') + + if (any(d_in /= d_out)) error stop 'test_read_write' + +end subroutine test_read_write + +end module test_HDF5_utilities diff --git a/src/test/test_prec.f90 b/src/test/test_prec.f90 new file mode 100644 index 000000000..fa18d01a1 --- /dev/null +++ b/src/test/test_prec.f90 @@ -0,0 +1,19 @@ +module test_prec + use prec + + implicit none(type,external) + + private + public :: prec_test + + contains + +subroutine prec_test() + + print*, 'begin test prec' + call prec_selfTest() + print*, 'end test prec' + +end subroutine prec_test + +end module test_prec