diff --git a/.github/workflows/centos_configure.sh b/.github/workflows/centos_configure.sh index 63117c7c2f9e..03d54604d3f0 100644 --- a/.github/workflows/centos_configure.sh +++ b/.github/workflows/centos_configure.sh @@ -38,9 +38,8 @@ cmake -H"${KRATOS_SOURCE}" -B"${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" \ ${KRATOS_CMAKE_OPTIONS_FLAGS} \ -DUSE_MPI=OFF \ -DPYBIND11_PYTHON_VERSION="3.5" \ --DCMAKE_CXX_FLAGS="${KRATOS_CMAKE_CXX_FLAGS} -std=c++11 -O0 -fopenmp -Wall" \ --DUSE_COTIRE=ON \ +-DCMAKE_CXX_FLAGS="${KRATOS_CMAKE_CXX_FLAGS} -std=c++11 -O0 -Wall" \ +-DCMAKE_UNITY_BUILD=ON \ # Buid -cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target all_unity -- -j1 && \ -cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target install/fast -- -j1 +cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target install -- -j2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af3321e5fd9d..b4e995c62094 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,19 +18,10 @@ jobs: compiler: [gcc, clang] env: KRATOS_BUILD_TYPE: ${{ matrix.build-type }} - MKLVARS_ARCHITECTURE: intel64 - MKLVARS_INTERFACE: lp64 container: image: kratosmultiphysics/kratos-image-ci-ubuntu-20-04:latest options: --user 1001 - env: - CCACHE_SLOPPINESS: pch_defines,time_macros - CCACHE_COMPILERCHECK: content - CCACHE_COMPRESS: true - CCACHE_NODISABLE: true - CCACHE_MAXSIZE: 500M - FC: gfortran-7 steps: - uses: rokroskar/workflow-run-cleanup-action@v0.2.2 @@ -39,24 +30,17 @@ jobs: - uses: actions/checkout@v2 - - name: Cache Build - id: cache-build - uses: actions/cache@v1 - with: - path: ~/.ccache - key: ${{ runner.os }}-${{ matrix.build-type }}-${{ matrix.compiler }}-ccache-${{ github.sha }} - restore-keys: ${{ runner.os }}-${{ matrix.build-type }}-${{ matrix.compiler }}-ccache- - - name: Build + shell: bash run: | if [ ${{ matrix.compiler }} = gcc ]; then - export CC=/usr/lib/ccache/gcc - export CXX=/usr/lib/ccache/g++ + export CC=/usr/bin/gcc + export CXX=/usr/bin/g++ export KRATOS_CMAKE_OPTIONS_FLAGS="-DUSE_EIGEN_MKL=ON -DUSE_EIGEN_FEAST=ON -DTRILINOS_EXCLUDE_AMESOS2_SOLVER=OFF -DMMG_ROOT=/external_libraries/mmg/mmg_5_5_1/ -DPMMG_ROOT=/external_libraries/ParMmg_5ffc6ad -DINCLUDE_PMMG=ON" export KRATOS_CMAKE_CXX_FLAGS="-std=c++11 -Werror -Wno-deprecated-declarations -Wignored-qualifiers" elif [ ${{ matrix.compiler }} = clang ]; then - export CC=clang-9 - export CXX=clang++-9 + export CC=/usr/bin/clang + export CXX=/usr/bin/clang++ export KRATOS_CMAKE_CXX_FLAGS="-Werror -Wno-deprecated-declarations" if [ ${{ matrix.build-type }} = FullDebug ]; then export KRATOS_CMAKE_CXX_FLAGS="${KRATOS_CMAKE_CXX_FLAGS} -std=c++17" @@ -68,59 +52,65 @@ jobs: echo 'Unsupported compiler: ${{ matrix.compiler }}' exit 1 fi - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh cp .github/workflows/configure.sh configure.sh bash configure.sh - ccache -s - name: Running small tests + shell: bash run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }}/libs python3 kratos/python_scripts/run_tests.py -l small -c python3 - name: Running MPICore C++ tests (2 Cores) + shell: bash timeout-minutes : 10 run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }}/libs mpiexec -np 2 python3 kratos/python_scripts/run_cpp_mpi_tests.py --using-mpi - name: Running MPICore C++ tests (3 Cores) + shell: bash timeout-minutes : 10 run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }}/libs mpiexec --oversubscribe -np 3 python3 kratos/python_scripts/run_cpp_mpi_tests.py --using-mpi - name: Running MPICore C++ tests (4 Cores) + shell: bash timeout-minutes : 10 run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }}/libs mpiexec --oversubscribe -np 4 python3 kratos/python_scripts/run_cpp_mpi_tests.py --using-mpi - name: Running Python MPI tests (2 Cores) + shell: bash run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }}/libs python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l small -n 2 - name: Running Python MPI tests (3 Cores) + shell: bash run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }}/libs python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l small -n 3 -f--oversubscribe - name: Running Python MPI tests (4 Cores) + shell: bash run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${{ matrix.build-type }}/libs python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l small -n 4 -f--oversubscribe @@ -135,18 +125,19 @@ jobs: - uses: actions/setup-python@v1 with: python-version: '3.6' - - name: Cache Build - id: cache-build - uses: actions/cache@v1 - with: - path: build - key: ${{ runner.os }}-build-${{ github.sha }} - restore-keys: ${{ runner.os }}-build- + + - name: Download boost + run: | + $url = "https://sourceforge.net/projects/boost/files/boost/1.74.0/boost_1_74_0.tar.gz/download" + (New-Object System.Net.WebClient).DownloadFile($url, "$env:TEMP\boost.tar.gz") + 7z.exe x "$env:TEMP\boost.tar.gz" -o"$env:TEMP\boostArchive" -y | Out-Null + 7z.exe x "$env:TEMP\boostArchive" -o"$env:TEMP\boost" -y | Out-Null - name: Installing dependencies shell: cmd run: | pip install numpy + pip install h5py - name: Build shell: cmd @@ -170,8 +161,6 @@ jobs: container: image: kratosmultiphysics/kratos-image-ci-centos7-python35:latest options: --user 1001 - env: - FC: gfortran-7 steps: - uses: rokroskar/workflow-run-cleanup-action@v0.2.2 @@ -190,3 +179,140 @@ jobs: export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/Custom export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/Custom/libs python3.5 kratos/python_scripts/run_tests.py -l small -c python3.5 + + + ubuntu-without-unity: + runs-on: ubuntu-latest + env: + KRATOS_BUILD_TYPE: Custom + + container: + image: kratosmultiphysics/kratos-image-ci-ubuntu-20-04:latest + env: + CCACHE_SLOPPINESS: pch_defines,time_macros + CCACHE_COMPILERCHECK: content + CCACHE_COMPRESS: true + CCACHE_NODISABLE: true + CCACHE_MAXSIZE: 500M + + steps: + - uses: rokroskar/workflow-run-cleanup-action@v0.2.2 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + - uses: actions/checkout@v2 + + - name: Cache Build + id: cache-build + uses: actions/cache@v1 + with: + path: ~/.ccache + key: ${{ runner.os }}-no-unity-ccache-${{ github.sha }} + restore-keys: ${{ runner.os }}-no-unity-ccache- + + - name: Build + shell: bash + run: | + export CC=/usr/lib/ccache/clang + export CXX=/usr/lib/ccache/clang++ + + export KRATOS_SOURCE="${KRATOS_SOURCE:-${PWD}}" + export KRATOS_BUILD="${KRATOS_SOURCE}/build" + export PYTHON_EXECUTABLE="/usr/bin/python3.8" + export KRATOS_INSTALL_PYTHON_USING_LINKS=ON + + # Configure + cmake -H"${KRATOS_SOURCE}" -B"${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" \ + -DUSE_MPI=ON \ + -DPYBIND11_PYTHON_VERSION="3.8" \ + -DINSTALL_RUNKRATOS=OFF + + # Buid + cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target install -- -j2 + + ccache -s + + + ubuntu-intel: + runs-on: ubuntu-latest + env: + KRATOS_BUILD_TYPE: Custom + + container: + image: kratosmultiphysics/kratos-image-ci-ubuntu-20-04:latest + options: --user 1001 + + steps: + - uses: rokroskar/workflow-run-cleanup-action@v0.2.2 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + - uses: actions/checkout@v2 + + - name: Build + shell: bash + run: | + export CC=icc + export CXX=icpc + source /opt/intel/oneapi/setvars.sh + cp .github/workflows/intel_configure.sh configure.sh + bash configure.sh + + - name: Running small tests + shell: bash + run: | + source /opt/intel/oneapi/setvars.sh + export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/Custom + export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/Custom/libs + python3 kratos/python_scripts/run_tests.py -l small -c python3 + + - name: Running MPICore C++ tests (2 Cores) + shell: bash + timeout-minutes : 10 + run: | + source /opt/intel/oneapi/setvars.sh + export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/Custom + export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/Custom/libs + mpiexec -np 2 python3 kratos/python_scripts/run_cpp_mpi_tests.py --using-mpi + + - name: Running MPICore C++ tests (3 Cores) + shell: bash + timeout-minutes : 10 + run: | + source /opt/intel/oneapi/setvars.sh + export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/Custom + export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/Custom/libs + mpiexec --oversubscribe -np 3 python3 kratos/python_scripts/run_cpp_mpi_tests.py --using-mpi + + - name: Running MPICore C++ tests (4 Cores) + shell: bash + timeout-minutes : 10 + run: | + source /opt/intel/oneapi/setvars.sh + export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/Custom + export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/Custom/libs + mpiexec --oversubscribe -np 4 python3 kratos/python_scripts/run_cpp_mpi_tests.py --using-mpi + + - name: Running Python MPI tests (2 Cores) + shell: bash + run: | + source /opt/intel/oneapi/setvars.sh + export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/Custom + export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/Custom/libs + python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l small -n 2 + + - name: Running Python MPI tests (3 Cores) + shell: bash + run: | + source /opt/intel/oneapi/setvars.sh + export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/Custom + export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/Custom/libs + python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l small -n 3 -f--oversubscribe + + - name: Running Python MPI tests (4 Cores) + shell: bash + run: | + source /opt/intel/oneapi/setvars.sh + export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/Custom + export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/Custom/libs + python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l small -n 4 -f--oversubscribe \ No newline at end of file diff --git a/.github/workflows/configure.cmd b/.github/workflows/configure.cmd index ae8b2ac06c92..44623fc9fc1c 100644 --- a/.github/workflows/configure.cmd +++ b/.github/workflows/configure.cmd @@ -27,23 +27,23 @@ set KRATOS_APPLICATIONS=%KRATOS_APPLICATIONS%%KRATOS_APP_DIR%\ShapeOptimizationA set KRATOS_APPLICATIONS=%KRATOS_APPLICATIONS%%KRATOS_APP_DIR%\ConstitutiveLawsApplication; set KRATOS_APPLICATIONS=%KRATOS_APPLICATIONS%%KRATOS_APP_DIR%\RANSApplication; set KRATOS_APPLICATIONS=%KRATOS_APPLICATIONS%%KRATOS_APP_DIR%\CompressiblePotentialFlowApplication; +set KRATOS_APPLICATIONS=%KRATOS_APPLICATIONS%%KRATOS_APP_DIR%\RomApplication; del /F /Q "%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%\cmake_install.cmake" del /F /Q "%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%\CMakeCache.txt" del /F /Q "%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%\CMakeFiles" -cmake ^ - -G"Visual Studio 16 2019" ^ - -H"%KRATOS_SOURCE%" ^ - -B"%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%" ^ - -DBOOST_ROOT="%BOOST_ROOT_1_72_0%" ^ - -DINSTALL_RUNKRATOS=OFF ^ - -DCMAKE_CXX_FLAGS="/Od /we4661 /we4804 /WX" ^ - -DFORCE_LOCAL_ZLIB_COMPILATION=ON ^ - -DUSE_COTIRE=ON || goto :error - -cmake --build "%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%" --target all_unity -- /property:configuration=%KRATOS_BUILD_TYPE% /p:Platform=x64 || goto :error -cmake --build "%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%" --target zlibstatic -- /property:configuration=%KRATOS_BUILD_TYPE% /p:Platform=x64 || goto :error +cmake ^ + -G"Visual Studio 16 2019" ^ + -H"%KRATOS_SOURCE%" ^ + -B"%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%" ^ + -DBOOST_ROOT="%TEMP%\boost" ^ + -DINSTALL_RUNKRATOS=OFF ^ + -DCMAKE_CXX_FLAGS="/Od /we4661 /we4804 /WX /wd4996" ^ + -DFORCE_LOCAL_ZLIB_COMPILATION=ON ^ + -DCMAKE_UNITY_BUILD=ON || goto :error + +cmake --build "%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%" --target all_build -- /property:configuration=%KRATOS_BUILD_TYPE% /p:Platform=x64 || goto :error cmake --build "%KRATOS_BUILD%\%KRATOS_BUILD_TYPE%" --target install -- /property:configuration=%KRATOS_BUILD_TYPE% /p:Platform=x64 || goto :error goto :EOF diff --git a/.github/workflows/configure.sh b/.github/workflows/configure.sh index 797271b12714..bbefb7df4204 100644 --- a/.github/workflows/configure.sh +++ b/.github/workflows/configure.sh @@ -46,6 +46,7 @@ add_app ${KRATOS_APP_DIR}/MultilevelMonteCarloApplication; add_app ${KRATOS_APP_DIR}/StatisticsApplication; add_app ${KRATOS_APP_DIR}/SwimmingDEMApplication; add_app ${KRATOS_APP_DIR}/ConstitutiveLawsApplication; +add_app ${KRATOS_APP_DIR}/RomApplication; # Clean clear @@ -64,9 +65,8 @@ ${KRATOS_CMAKE_OPTIONS_FLAGS} \ -DTRILINOS_INCLUDE_DIR="/usr/include/trilinos" \ -DTRILINOS_LIBRARY_DIR="/usr/lib/x86_64-linux-gnu" \ -DTRILINOS_LIBRARY_PREFIX="trilinos_" \ --DUSE_COTIRE=ON \ +-DCMAKE_UNITY_BUILD=ON \ -DINCLUDE_MMG=ON \ # Buid -cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target all_unity -- -j1 && \ -cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target install/fast -- -j1 +cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target install -- -j2 diff --git a/.github/workflows/intel_configure.sh b/.github/workflows/intel_configure.sh new file mode 100644 index 000000000000..77585d6286a0 --- /dev/null +++ b/.github/workflows/intel_configure.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# You can use your interpreter of choice (bash, sh, zsh, ...) + +# For any question please contact with us in: +# - https://github.com/KratosMultiphysics/Kratos + +# Optional parameters: +# You can find a list will all the compiation options in INSTALL.md or here: +# - https://github.com/KratosMultiphysics/Kratos/wiki/Compilation-options + +add_app () { + export KRATOS_APPLICATIONS="${KRATOS_APPLICATIONS}$1;" +} + +# Set variables +export KRATOS_SOURCE="${KRATOS_SOURCE:-${PWD}}" +export KRATOS_BUILD="${KRATOS_SOURCE}/build" +export KRATOS_APP_DIR="${KRATOS_SOURCE}/applications" +export PYTHON_EXECUTABLE="/usr/bin/python3.8" +export KRATOS_INSTALL_PYTHON_USING_LINKS=ON + +# Set applications to compile +# add_app ${KRATOS_APP_DIR}/ConvectionDiffusionApplication; +# add_app ${KRATOS_APP_DIR}/LinearSolversApplication; +# add_app ${KRATOS_APP_DIR}/StructuralMechanicsApplication; +# add_app ${KRATOS_APP_DIR}/FluidDynamicsApplication; +# add_app ${KRATOS_APP_DIR}/MeshMovingApplication; +# add_app ${KRATOS_APP_DIR}/DEMApplication; +# add_app ${KRATOS_APP_DIR}/CSharpWrapperApplication; +# add_app ${KRATOS_APP_DIR}/MetisApplication; +# add_app ${KRATOS_APP_DIR}/TrilinosApplication; +# add_app ${KRATOS_APP_DIR}/ShapeOptimizationApplication; +# add_app ${KRATOS_APP_DIR}/CoSimulationApplication; +# add_app ${KRATOS_APP_DIR}/CableNetApplication; +# add_app ${KRATOS_APP_DIR}/RANSApplication; +# add_app ${KRATOS_APP_DIR}/MappingApplication; +# add_app ${KRATOS_APP_DIR}/FSIApplication; +# add_app ${KRATOS_APP_DIR}/MeshingApplication; +# add_app ${KRATOS_APP_DIR}/CompressiblePotentialFlowApplication; +# add_app ${KRATOS_APP_DIR}/HDF5Application; +# add_app ${KRATOS_APP_DIR}/ContactStructuralMechanicsApplication; +# add_app ${KRATOS_APP_DIR}/IgaApplication; +# add_app ${KRATOS_APP_DIR}/ParticleMechanicsApplication; +# add_app ${KRATOS_APP_DIR}/ChimeraApplication; +# add_app ${KRATOS_APP_DIR}/MultilevelMonteCarloApplication; +# add_app ${KRATOS_APP_DIR}/StatisticsApplication; +# add_app ${KRATOS_APP_DIR}/SwimmingDEMApplication; +# add_app ${KRATOS_APP_DIR}/ConstitutiveLawsApplication; + +# Clean +clear +rm -rf "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}/cmake_install.cmake" +rm -rf "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}/CMakeCache.txt" +rm -rf "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}/CMakeFiles" + +echo "Kratos build type is ${KRATOS_BUILD_TYPE}" + +# Configure +cmake -H"${KRATOS_SOURCE}" -B"${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" \ +${KRATOS_CMAKE_OPTIONS_FLAGS} \ +-DINSTALL_RUNKRATOS=OFF \ +-DUSE_MPI=ON \ +-DPYBIND11_PYTHON_VERSION="3.8" \ +-DCMAKE_CXX_FLAGS="${KRATOS_CMAKE_CXX_FLAGS} -O0 -Wall" \ +-DTRILINOS_INCLUDE_DIR="/usr/include/trilinos" \ +-DTRILINOS_LIBRARY_DIR="/usr/lib/x86_64-linux-gnu" \ +-DTRILINOS_LIBRARY_PREFIX="trilinos_" \ +-DCMAKE_UNITY_BUILD=ON + +# Buid +cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target install -- -j2 diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index 2e8e65bfc774..5c959d343278 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -4,6 +4,8 @@ on: pull_request: paths: - '.github/workflows/nightly_build.yml' + - '.github/workflows/configure.sh' + - '.github/workflows/configure.cmd' schedule: - cron: '0 1 * * *' @@ -20,9 +22,6 @@ jobs: compiler: [gcc, clang] env: KRATOS_BUILD_TYPE: Release - MKLVARS_ARCHITECTURE: intel64 - MKLVARS_INTERFACE: lp64 - FC: gfortran-7 container: image: kratosmultiphysics/kratos-image-ci-ubuntu-20-04:latest @@ -36,48 +35,53 @@ jobs: - uses: actions/checkout@v2 - name: Build + shell: bash run: | if [ ${{ matrix.compiler }} = gcc ]; then - export CC=gcc - export CXX=g++ + export CC=/usr/bin/gcc + export CXX=/usr/bin/g++ export KRATOS_CMAKE_OPTIONS_FLAGS="-DUSE_EIGEN_MKL=ON -DUSE_EIGEN_FEAST=ON -DTRILINOS_EXCLUDE_AMESOS2_SOLVER=OFF -DMMG_ROOT=/external_libraries/mmg/mmg_5_5_1/ -DPMMG_ROOT=/external_libraries/ParMmg_5ffc6ad -DINCLUDE_PMMG=ON" export KRATOS_CMAKE_CXX_FLAGS="-Wignored-qualifiers" elif [ ${{ matrix.compiler }} = clang ]; then - export CC=clang-9 - export CXX=clang++-9 + export CC=/usr/bin/clang + export CXX=/usr/bin/clang++ export KRATOS_CMAKE_OPTIONS_FLAGS="-DTRILINOS_EXCLUDE_AMESOS2_SOLVER=OFF -DMMG_ROOT=/external_libraries/mmg/mmg_5_4_1/" else echo 'Unsupported compiler: ${{ matrix.compiler }}' exit 1 fi - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh cp .github/workflows/configure.sh configure.sh # maybe use different configure script in the future bash configure.sh - name: Running tests + shell: bash run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${KRATOS_BUILD_TYPE} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${KRATOS_BUILD_TYPE}/libs python3 kratos/python_scripts/run_tests.py -l nightly -c python3 - name: Running Python MPI tests (2 Cores) + shell: bash run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${KRATOS_BUILD_TYPE} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${KRATOS_BUILD_TYPE}/libs python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l nightly -n 2 - name: Running Python MPI tests (3 Cores) + shell: bash run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${KRATOS_BUILD_TYPE} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${KRATOS_BUILD_TYPE}/libs python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l nightly -n 3 -f--oversubscribe - name: Running Python MPI tests (4 Cores) + shell: bash run: | - . /opt/intel/mkl/bin/mklvars.sh + source /opt/intel/oneapi/setvars.sh export PYTHONPATH=${PYTHONPATH}:${GITHUB_WORKSPACE}/bin/${KRATOS_BUILD_TYPE} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${GITHUB_WORKSPACE}/bin/${KRATOS_BUILD_TYPE}/libs python3 kratos/python_scripts/testing/run_python_mpi_tests.py -l nightly -n 4 -f--oversubscribe @@ -95,10 +99,18 @@ jobs: with: python-version: '3.6' + - name: Download boost + run: | + $url = "https://sourceforge.net/projects/boost/files/boost/1.74.0/boost_1_74_0.tar.gz/download" + (New-Object System.Net.WebClient).DownloadFile($url, "$env:TEMP\boost.tar.gz") + 7z.exe x "$env:TEMP\boost.tar.gz" -o"$env:TEMP\boostArchive" -y | Out-Null + 7z.exe x "$env:TEMP\boostArchive" -o"$env:TEMP\boost" -y | Out-Null + - name: Installing dependencies shell: cmd run: | pip install numpy + pip install h5py - name: Build shell: cmd diff --git a/.gitignore b/.gitignore index ee1ad56e6966..55aa9e63c8ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ ### ATTENTION ### # This is the GLOBAL gitignore, please do NOT change this file, # unless it should be available for everyone -# Please change the LOCAL gitignore (.git/info/exclude) to cutomize +# Please change the LOCAL gitignore (.git/info/exclude) to customize # exluding files/folders from being recognized by git # Recovery files diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d4845179ec5..e51ae1ff26e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,15 +105,27 @@ if(NOT CMAKE_BUILD_TYPE) endif(NOT CMAKE_BUILD_TYPE) set (KratosMultiphysics_BUILD_TYPE ${CMAKE_BUILD_TYPE}) - -if(USE_COTIRE MATCHES ON) - include(cotire) - set(CMAKE_SKIP_RPATH ON) - - if(${MSVC}) - set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY True) - endif(${MSVC}) -endif(USE_COTIRE MATCHES ON) +# Unitary builds with version is lower than 3.16 deactivate +IF(CMAKE_VERSION VERSION_LESS "3.16.0") + IF(CMAKE_UNITY_BUILD MATCHES ON) + SET(CMAKE_UNITY_BUILD OFF) + ENDIF(CMAKE_UNITY_BUILD MATCHES ON) +ELSE(CMAKE_VERSION VERSION_LESS "3.16.0") + IF(USE_COTIRE MATCHES ON) + # Legacy Unitary build + MESSAGE(STATUS "Using USE_COTIRE is deprecated and was replaced by CMAKE_UNITY_BUILD.") + SET(CMAKE_UNITY_BUILD ON) + ENDIF(USE_COTIRE MATCHES ON) + # Some checks + IF(CMAKE_UNITY_BUILD MATCHES ON) + IF(NOT DEFINED KRATOS_UNITY_BUILD_BATCH_SIZE) + SET(KRATOS_UNITY_BUILD_BATCH_SIZE 32) + ENDIF(NOT DEFINED KRATOS_UNITY_BUILD_BATCH_SIZE) + IF(${MSVC}) + SET(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY True) + ENDIF(${MSVC}) + ENDIF(CMAKE_UNITY_BUILD MATCHES ON) +ENDIF(CMAKE_VERSION VERSION_LESS "3.16.0") # Get subversion data. This is done automagically by the cmakes include (GenerateExportHeader) diff --git a/INSTALL.md b/INSTALL.md index 7c74f7634812..f4a2d7ed3a9c 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -151,6 +151,7 @@ Windows ```Shell ./path_to_kratos/scripts/configure.bat ``` +Note: after installing Visual Studio, in some Windows systems the console does not have direct access to the Visual Studio Compiler. In order to make sure the compiler is available, try typing 'cl'. Use this console to compile Kratos if the compiler responds. In case of error, instead of using the standard Windows console, open the Native Tools Command Prompt console and launch the compilation from there. The example scripts for every system are shown next. @@ -436,22 +437,20 @@ Enables(Default) or Disables the compilation of the embedded python interpreter Enables(Default) or Disables the compilation of the C++ unitary tests for Kratos and Applications. ### Compilation Performance -`-DUSE_COTIRE=ON/OFF` +`-DCMAKE_UNITY_BUILD=ON/OFF` -Enables or Disables(default) the use of [cotire](https://github.com/sakra/cotire) to speedup compilation by using unitary builds. +Enables or Disables(default) the use of [cmake unity build](https://cmake.org/cmake/help/latest/prop_tgt/UNITY_BUILD.html) to speedup compilation by using unitary builds. Please notice that enabling this options can greatly increase the amount of memory needed to compile some targets, specially if combined with -jx. In order to install and compile with this switch please use: On Linux ```shell -cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target all_unity -- -j1 && \ -cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target install/fast -- -j1 +cmake --build "${KRATOS_BUILD}/${KRATOS_BUILD_TYPE}" --target install -- -j1 ``` On Windows ```shell -cmake --build "%KRATOS_BUILD%/%KRATOS_BUILD_TYPE%" --target all_unity -- /property:configuration=%KRATOS_BUILD_TYPE% /p:Platform=x64 -cmake --build "%KRATOS_BUILD%/%KRATOS_BUILD_TYPE%" --target install -- /property:configuration=%KRATOS_BUILD_TYPE% /p:Platform=x64 +cmake --build "%KRATOS_BUILD%/%KRATOS_BUILD_TYPE%" --target install -- /property:configuration=%KRATOS_BUILD_TYPE% /p:Platform=x64 ``` Instead of the regular install target. diff --git a/applications/CSharpWrapperApplication/CMakeLists.txt b/applications/CSharpWrapperApplication/CMakeLists.txt index 55abfb38cde6..839e2173a979 100644 --- a/applications/CSharpWrapperApplication/CMakeLists.txt +++ b/applications/CSharpWrapperApplication/CMakeLists.txt @@ -49,6 +49,12 @@ pybind11_add_module(KratosCSharpWrapperApplication MODULE THIN_LTO ${KRATOS_WRAP target_link_libraries(KratosCSharpWrapperApplication PRIVATE KratosCSharpWrapperCore) set_target_properties(KratosCSharpWrapperApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosCSharpWrapperCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosCSharpWrapperApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES) # message("TestApplication subdir inc_dirs = ${inc_dirs}") @@ -62,12 +68,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosCSharpWrapperApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosCSharpWrapperCore) - cotire(KratosCSharpWrapperApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/CSharpWrapperApplication.py KratosMultiphysics/CSharpWrapperApplication/__init__.py ) diff --git a/applications/CableNetApplication/CMakeLists.txt b/applications/CableNetApplication/CMakeLists.txt index a4cd85c92baa..216c8f5ab31b 100644 --- a/applications/CableNetApplication/CMakeLists.txt +++ b/applications/CableNetApplication/CMakeLists.txt @@ -38,6 +38,12 @@ pybind11_add_module(KratosCableNetApplication MODULE THIN_LTO ${KRATOS_CABLE_NET target_link_libraries(KratosCableNetApplication PRIVATE KratosCableNetCore) set_target_properties(KratosCableNetApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosCableNetCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosCableNetApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosCableNetApplication PROPERTIES SUFFIX .pyd) @@ -48,12 +54,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosCableNetApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosCableNetCore) - cotire(KratosCableNetApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/CableNetApplication.py KratosMultiphysics/CableNetApplication/__init__.py ) diff --git a/applications/ChimeraApplication/CMakeLists.txt b/applications/ChimeraApplication/CMakeLists.txt index 2563d6e83bc3..35b499d3c6c5 100644 --- a/applications/ChimeraApplication/CMakeLists.txt +++ b/applications/ChimeraApplication/CMakeLists.txt @@ -38,6 +38,12 @@ pybind11_add_module(KratosChimeraApplication MODULE THIN_LTO ${KRATOS_CHIMERA_AP target_link_libraries(KratosChimeraApplication PRIVATE KratosChimeraApplicationCore) set_target_properties(KratosChimeraApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosChimeraApplicationCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosChimeraApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosChimeraApplication PROPERTIES SUFFIX .pyd) @@ -48,15 +54,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosChimeraApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosChimeraApplicationCore) - cotire(KratosChimeraApplication) -endif(USE_COTIRE MATCHES ON) - - - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/ChimeraApplication.py KratosMultiphysics/ChimeraApplication/__init__.py ) diff --git a/applications/CoSimulationApplication/CMakeLists.txt b/applications/CoSimulationApplication/CMakeLists.txt index cc7aeba2b888..9757b43c1d8f 100644 --- a/applications/CoSimulationApplication/CMakeLists.txt +++ b/applications/CoSimulationApplication/CMakeLists.txt @@ -38,6 +38,12 @@ pybind11_add_module(KratosCoSimulationApplication MODULE THIN_LTO ${KRATOS_CO_SI target_link_libraries(KratosCoSimulationApplication PRIVATE KratosCoSimulationCore) set_target_properties(KratosCoSimulationApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosCoSimulationCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosCoSimulationApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # Making the cpp_test_solver_one and cpp_test_solver_two executables add_executable(ping ${KRATOS_CO_SIMULATION_TESTING_CPP_PING_SOURCES}) add_executable(pong ${KRATOS_CO_SIMULATION_TESTING_CPP_PONG_SOURCES}) @@ -52,12 +58,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosCoSimulationApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosCoSimulationCore) - cotire(KratosCoSimulationApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/CoSimulationApplication.py KratosMultiphysics/CoSimulationApplication/__init__.py ) diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/co_sim_io.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/co_sim_io.hpp index d684340d63f9..e94035914902 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/co_sim_io.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/co_sim_io.hpp @@ -10,8 +10,8 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_H_INCLUDED -#define CO_SIM_IO_H_INCLUDED +#ifndef CO_SIM_IO_INCLUDED +#define CO_SIM_IO_INCLUDED /* This file defines the IO of Kratos-CoSimulation for the exchange of data with external solvers. @@ -37,6 +37,7 @@ Note that this introduces dependencies such as e.g. boost (header-only version) // Project includes #include "impl/define.hpp" #include "impl/info.hpp" +#include "impl/model_part.hpp" namespace CoSimIO { @@ -61,20 +62,13 @@ inline Info ExportData( const TContainerType& rData); -template inline Info ImportMesh( const Info& I_Info, - TDoubleContainerType& rNodalCoordinates, - TIntContainerType& rElementConnectivities, - TIntContainerType& rElementTypes); + ModelPart& O_ModelPart); -template inline Info ExportMesh( const Info& I_Info, - const TDoubleContainerType& rNodalCoordinates, - const TIntContainerType& rElementConnectivities, - const TIntContainerType& rElementTypes); - + const ModelPart& I_ModelPart); inline Info ImportInfo( const Info& I_Info); @@ -83,8 +77,6 @@ inline Info ExportInfo( const Info& I_Info); -inline Info IsConverged(const Info& I_Info); - inline Info Run(const Info& I_Info); template @@ -96,4 +88,4 @@ inline Info Register( #include "impl/co_sim_io_impl.hpp" -#endif // CO_SIM_IO_H_INCLUDED +#endif // CO_SIM_IO_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/co_sim_io_impl.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/co_sim_io_impl.hpp index dbce81bd6971..279a4943d1c3 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/co_sim_io_impl.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/co_sim_io_impl.hpp @@ -10,8 +10,8 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_IMPL_H_INCLUDED -#define CO_SIM_IO_IMPL_H_INCLUDED +#ifndef CO_SIM_IO_IMPL_INCLUDED +#define CO_SIM_IO_IMPL_INCLUDED /* This file contains the implementation of the functions defined in "co_sim_io.hpp" @@ -23,6 +23,7 @@ This file contains the implementation of the functions defined in "co_sim_io.hpp // Project includes #include "connection.hpp" +#include "utilities.hpp" #include "version.hpp" namespace CoSimIO { @@ -42,14 +43,6 @@ static Connection& GetConnection(const std::string& rConnectionName) return *s_co_sim_connections.at(rConnectionName); } -inline void SendControlSignal( - const Info& I_Info, - const CoSimIO::ControlSignal Signal) -{ - const std::string connection_name = I_Info.Get("connection_name"); - Internals::GetConnection(connection_name).SendControlSignal("", Signal); -} - } // namespace Internals inline Info Hello() @@ -76,11 +69,24 @@ inline Info Hello() inline Info Connect(const Info& I_Settings) { using namespace Internals; - const std::string connection_name = I_Settings.Get("connection_name"); - CO_SIM_IO_ERROR_IF(HasIO(connection_name)) << "A connection for \"" << connection_name << "\" already exists!" << std::endl; + const std::string my_name = I_Settings.Get("my_name"); + const std::string connect_to = I_Settings.Get("connect_to"); + + // perform some checks + CheckEntry(my_name, "my_name"); + CheckEntry(connect_to, "connect_to"); + CO_SIM_IO_ERROR_IF(my_name == connect_to) << "Connecting to self is not allowed!" << std::endl; - s_co_sim_connections[connection_name] = std::unique_ptr(new Connection(connection_name, I_Settings)); - return GetConnection(connection_name).Connect(); + const std::string connection_name = CreateConnectionName(my_name, connect_to); + + CO_SIM_IO_ERROR_IF(HasIO(connection_name)) << "A connection from \"" << my_name << "\" to \"" << connect_to << "\"already exists!" << std::endl; + + s_co_sim_connections[connection_name] = std::unique_ptr(new Connection(I_Settings)); + + auto info = GetConnection(connection_name).Connect(I_Settings); + info.Set("connection_name", connection_name); + + return info; } inline Info Disconnect(const Info& I_Info) @@ -89,10 +95,10 @@ inline Info Disconnect(const Info& I_Info) const std::string connection_name = I_Info.Get("connection_name"); CO_SIM_IO_ERROR_IF_NOT(HasIO(connection_name)) << "Trying to disconnect connection \"" << connection_name << "\" which does not exist!" << std::endl; - auto info = GetConnection(connection_name).Disconnect(); + auto info = GetConnection(connection_name).Disconnect(I_Info); s_co_sim_connections.erase(connection_name); - return info; // TODO use this + return info; } // Version for C++, there this input is a std::vector, which we have to wrap before passing it on @@ -102,11 +108,9 @@ inline Info ImportData( std::vector& rData) { const std::string connection_name = I_Info.Get("connection_name"); - const std::string identifier = I_Info.Get("identifier"); using namespace CoSimIO::Internals; std::unique_ptr> p_container(new DataContainerStdVector(rData)); - // TODO maybe pass the Info into the function (only changes under the hood necessary) - return GetConnection(connection_name).ImportData(identifier, *p_container); + return GetConnection(connection_name).ImportData(I_Info, *p_container); } // Version for C and fortran, there we already get a container @@ -116,9 +120,7 @@ inline Info ImportData( CoSimIO::Internals::DataContainer& rData) { const std::string connection_name = I_Info.Get("connection_name"); - const std::string identifier = I_Info.Get("identifier"); - // TODO maybe pass the Info into the function (only changes under the hood necessary) - return Internals::GetConnection(connection_name).ImportData(identifier, rData); + return Internals::GetConnection(connection_name).ImportData(I_Info, rData); } // Version for C++, there this input is a std::vector, which we have to wrap before passing it on @@ -128,11 +130,9 @@ inline Info ExportData( const std::vector& rData) { const std::string connection_name = I_Info.Get("connection_name"); - const std::string identifier = I_Info.Get("identifier"); using namespace CoSimIO::Internals; std::unique_ptr> p_container(new DataContainerStdVectorReadOnly(rData)); - // TODO maybe pass the Info into the function (only changes under the hood necessary) - return GetConnection(connection_name).ExportData(identifier, *p_container); + return GetConnection(connection_name).ExportData(I_Info, *p_container); } // Version for C and fortran, there we already get a container @@ -142,100 +142,43 @@ inline Info ExportData( const CoSimIO::Internals::DataContainer& rData) { const std::string connection_name = I_Info.Get("connection_name"); - const std::string identifier = I_Info.Get("identifier"); - // TODO maybe pass the Info into the function (only changes under the hood necessary) - return Internals::GetConnection(connection_name).ExportData(identifier, rData); + return Internals::GetConnection(connection_name).ExportData(I_Info, rData); } -template<> inline Info ImportMesh( const Info& I_Info, - std::vector& rNodalCoordinates, - std::vector& rElementConnectivities, - std::vector& rElementTypes) -{ - const std::string connection_name = I_Info.Get("connection_name"); - const std::string identifier = I_Info.Get("identifier"); - using namespace CoSimIO::Internals; - std::unique_ptr> p_container_coords(new DataContainerStdVector(rNodalCoordinates)); - std::unique_ptr> p_container_conn(new DataContainerStdVector(rElementConnectivities)); - std::unique_ptr> p_container_types(new DataContainerStdVector(rElementTypes)); - // TODO maybe pass the Info into the function (only changes under the hood necessary) - return Internals::GetConnection(connection_name).ImportMesh(identifier, *p_container_coords, *p_container_conn, *p_container_types); -} - -template<> -inline Info ImportMesh( - const Info& I_Info, - CoSimIO::Internals::DataContainer& rNodalCoordinates, - CoSimIO::Internals::DataContainer& rElementConnectivities, - CoSimIO::Internals::DataContainer& rElementTypes) -{ - const std::string connection_name = I_Info.Get("connection_name"); - const std::string identifier = I_Info.Get("identifier"); - // TODO maybe pass the Info into the function (only changes under the hood necessary) - return Internals::GetConnection(connection_name).ImportMesh(identifier, rNodalCoordinates, rElementConnectivities, rElementTypes); -} - -template<> -inline Info ExportMesh( - const Info& I_Info, - const std::vector& rNodalCoordinates, - const std::vector& rElementConnectivities, - const std::vector& rElementTypes) + ModelPart& O_ModelPart) { const std::string connection_name = I_Info.Get("connection_name"); - const std::string identifier = I_Info.Get("identifier"); - using namespace CoSimIO::Internals; - std::unique_ptr> p_container_coords(new DataContainerStdVectorReadOnly(rNodalCoordinates)); - std::unique_ptr> p_container_conn(new DataContainerStdVectorReadOnly(rElementConnectivities)); - std::unique_ptr> p_container_types(new DataContainerStdVectorReadOnly(rElementTypes)); - // TODO maybe pass the Info into the function (only changes under the hood necessary) - return Internals::GetConnection(connection_name).ExportMesh(identifier, *p_container_coords, *p_container_conn, *p_container_types); + return CoSimIO::Internals::GetConnection(connection_name).ImportMesh(I_Info, O_ModelPart); } -template<> inline Info ExportMesh( const Info& I_Info, - const CoSimIO::Internals::DataContainer& rNodalCoordinates, - const CoSimIO::Internals::DataContainer& rElementConnectivities, - const CoSimIO::Internals::DataContainer& rElementTypes) + const ModelPart& I_ModelPart) { const std::string connection_name = I_Info.Get("connection_name"); - const std::string identifier = I_Info.Get("identifier"); - // TODO maybe pass the Info into the function (only changes under the hood necessary) - return Internals::GetConnection(connection_name).ExportMesh(identifier, rNodalCoordinates, rElementConnectivities, rElementTypes); + return CoSimIO::Internals::GetConnection(connection_name).ExportMesh(I_Info, I_ModelPart); } inline Info ImportInfo( const Info& I_Info) { const std::string connection_name = I_Info.Get("connection_name"); - // Internals::GetConnection(connection_name).ImportInfo(rInfo); - return Info(); // TODO use this + return Internals::GetConnection(connection_name).ImportInfo(I_Info); } inline Info ExportInfo( const Info& I_Info) { const std::string connection_name = I_Info.Get("connection_name"); - // Internals::GetConnection(connection_name).ExportInfo(rInfo); - return Info(); // TODO use this -} - -inline Info IsConverged(const Info& I_Info) -{ - const std::string connection_name = I_Info.Get("connection_name"); - const bool is_converged = Internals::GetConnection(connection_name).IsConverged(); - Info info; - info.Set("is_converged", is_converged); - return info; + return Internals::GetConnection(connection_name).ExportInfo(I_Info); } inline Info Run(const Info& I_Info) { const std::string connection_name = I_Info.Get("connection_name"); - return Internals::GetConnection(connection_name).Run(); + return Internals::GetConnection(connection_name).Run(I_Info); } @@ -246,17 +189,9 @@ inline Info Register( { using namespace CoSimIO::Internals; - auto fct_callback = [I_FunctionPointer](const Info& I_Info) - { - Info info = I_FunctionPointer(I_Info); - return info; - }; - const std::string connection_name = I_Info.Get("connection_name"); const std::string function_name = I_Info.Get("function_name"); - Internals::GetConnection(connection_name).Register(function_name, fct_callback); - - return Info(); // TODO use this + return Internals::GetConnection(connection_name).Register(function_name, I_FunctionPointer); } template<> @@ -274,11 +209,9 @@ inline Info Register( const std::string connection_name = I_Info.Get("connection_name"); const std::string function_name = I_Info.Get("function_name"); - Internals::GetConnection(connection_name).Register(function_name, fct_callback); - - return Info(); // TODO use this + return Internals::GetConnection(connection_name).Register(function_name, fct_callback); } } // namespace CoSimIO -#endif // CO_SIM_IO_IMPL_H_INCLUDED +#endif // CO_SIM_IO_IMPL_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/communication.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/communication.hpp index f1732f6fade5..9ceec90806fe 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/communication.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/communication.hpp @@ -10,179 +10,239 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_COMMUNICATION_H_INCLUDED -#define CO_SIM_IO_COMMUNICATION_H_INCLUDED +#ifndef CO_SIM_IO_COMMUNICATION_INCLUDED +#define CO_SIM_IO_COMMUNICATION_INCLUDED // System includes +#include // Project includes #include "../info.hpp" #include "../data_container.hpp" +#include "../model_part.hpp" +#include "../filesystem_inc.hpp" +#include "../utilities.hpp" +#include "../version.hpp" namespace CoSimIO { namespace Internals { + class Communication { public: - explicit Communication(const std::string& rName, const Info& I_Settings, const bool IsConnectionMaster) : mConnectionName(rName), mIsConnectionMaster(IsConnectionMaster) - { - if (I_Settings.Has("echo_level")) { - mEchoLevel = I_Settings.Get("echo_level"); - } - if (I_Settings.Has("print_timing")) { - mPrintTiming = I_Settings.Get("print_timing"); + explicit Communication(const Info& I_Settings) + : mMyName(I_Settings.Get("my_name")), + mConnectTo(I_Settings.Get("connect_to")), + mWorkingDirectory(I_Settings.Get("working_directory", fs::relative(fs::current_path()).string())), + mEchoLevel(I_Settings.Get("echo_level", 0)), + mPrintTiming(I_Settings.Get("print_timing", false)) + { + if (I_Settings.Has("is_primary_connection")) { + mIsPrimaryConnection = I_Settings.Get("is_primary_connection"); + mPrimaryWasExplicitlySpecified = true; + } else { + // automatically determine the primary connection in case the user didn't specify it + mIsPrimaryConnection = mMyName < mConnectTo; + mPrimaryWasExplicitlySpecified = false; } + mConnectionName = CreateConnectionName(mMyName, mConnectTo); + + CO_SIM_IO_ERROR_IF_NOT(fs::exists(mWorkingDirectory)) << "The working directory " << mWorkingDirectory << " does not exist!" << std::endl; } virtual ~Communication() = default; // impl of disconnect has to be in derived class due to order of class destruction - bool Connect() + Info Connect(const Info& I_Info) { - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Connecting \"" << mConnectionName << "\" as Connection-" << (mIsConnectionMaster ? "MASTER" : "SLAVE") << " ..." << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) + << "Establishing connection for \"" << mConnectionName + << "\"\n from: \"" << mMyName + << "\"\n to: \"" << mConnectTo + << "\"\n as " << (mIsPrimaryConnection ? "PRIMARY" : "SECONDARY") + << " connection; working directory: " << mWorkingDirectory << " ..." << std::endl; CO_SIM_IO_ERROR_IF(mIsConnected) << "A connection was already established!" << std::endl; - mIsConnected = ConnectDetail(); + Info connect_detail_info = ConnectDetail(I_Info); + mIsConnected = connect_detail_info.Get("is_connected"); + connect_detail_info.Set("connection_status", ConnectionStatus::Connected); + connect_detail_info.Set("working_directory", mWorkingDirectory.string()); CO_SIM_IO_ERROR_IF_NOT(mIsConnected) << "Connection was not successful!" << std::endl; CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Connection established" << std::endl; - return mIsConnected; + PerformCompatibilityCheck(); + + return connect_detail_info; } - bool Disconnect() + Info Disconnect(const Info& I_Info) { CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Disconnecting \"" << mConnectionName << "\" ..." << std::endl; if (mIsConnected) { - mIsConnected = !DisconnectDetail(); + Info disconnect_detail_info = DisconnectDetail(I_Info); + mIsConnected = disconnect_detail_info.Get("is_connected"); + if (mIsConnected) { CO_SIM_IO_INFO("CoSimIO") << "Warning: Disconnect was not successful!" << std::endl; - return false; + disconnect_detail_info.Set("connection_status", ConnectionStatus::DisconnectionError); + } else { + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Disconnecting successful" << std::endl; + disconnect_detail_info.Set("connection_status", ConnectionStatus::Disconnected); } + return disconnect_detail_info; + } else { CO_SIM_IO_INFO("CoSimIO") << "Warning: Calling Disconnect but there was no active connection!" << std::endl; - return false; + Info disconnect_info; + disconnect_info.Set("is_connected", false); + disconnect_info.Set("connection_status", ConnectionStatus::DisconnectionError); + return disconnect_info; } - - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Disconnecting successful" << std::endl; - - return true; - } - - void SendControlSignal(const std::string& rIdentifier, const CoSimIO::ControlSignal Signal) - { - CheckConnection(); SendControlSignalDetail(rIdentifier, Signal); - } - CoSimIO::ControlSignal RecvControlSignal(std::string& rIdentifier) - { - CheckConnection(); return RecvControlSignalDetail(rIdentifier); } template - void ImportData(Args&&... args) + Info ExportInfo(Args&&... args) { - CheckConnection(); ImportDataImpl(std::forward(args)...); + CheckConnection(); return ExportInfoImpl(std::forward(args)...); } template - void ExportData(Args&&... args) + Info ImportInfo(Args&&... args) { - CheckConnection(); ExportDataImpl(std::forward(args)...); + CheckConnection(); return ImportInfoImpl(std::forward(args)...); } template - void ImportMesh(Args&&... args) + Info ImportData(Args&&... args) { - CheckConnection(); ImportMeshImpl(std::forward(args)...); + CheckConnection(); return ImportDataImpl(std::forward(args)...); } template - void ExportMesh(Args&&... args) + Info ExportData(Args&&... args) { - CheckConnection(); ExportMeshImpl(std::forward(args)...); + CheckConnection(); return ExportDataImpl(std::forward(args)...); } template - void ImportGeometry(Args&&... args) + Info ImportMesh(Args&&... args) { - CheckConnection(); // ImportGeometryImpl(std::forward(args)...); + CheckConnection(); return ImportMeshImpl(std::forward(args)...); } template - void ExportGeometry(Args&&... args) + Info ExportMesh(Args&&... args) { - CheckConnection(); // ExportGeometryImpl(std::forward(args)...); + CheckConnection(); return ExportMeshImpl(std::forward(args)...); } protected: std::string GetConnectionName() const {return mConnectionName;} + fs::path GetWorkingDirectory() const {return mWorkingDirectory;} int GetEchoLevel() const {return mEchoLevel;} - bool GetIsConnectionMaster() const {return mIsConnectionMaster;} + bool GetIsPrimaryConnection() const {return mIsPrimaryConnection;} bool GetPrintTiming() const {return mPrintTiming;} bool GetIsConnected() const {return mIsConnected;} private: std::string mConnectionName; + std::string mMyName; + std::string mConnectTo; + fs::path mWorkingDirectory; int mEchoLevel = 1; - bool mIsConnectionMaster = false; + bool mIsPrimaryConnection; + bool mPrimaryWasExplicitlySpecified; bool mPrintTiming = false; bool mIsConnected = false; - virtual bool ConnectDetail() = 0; - virtual bool DisconnectDetail() = 0; + void CheckConnection() + { + CO_SIM_IO_ERROR_IF_NOT(mIsConnected) << "No active connection exists!" << std::endl;; + } - virtual void SendControlSignalDetail(const std::string& rIdentifier, CoSimIO::ControlSignal Signal) + // new interface, functions return Info + virtual Info ConnectDetail(const Info& I_Info) = 0; + virtual Info DisconnectDetail(const Info& I_Info) = 0; + + virtual Info ImportInfoImpl(const Info& I_Info) { - CO_SIM_IO_ERROR << "SendControlSignalDetail not implemented for this comm-type" << std::endl; + CO_SIM_IO_ERROR << "ImportInfo not implemented for this comm-type" << std::endl; + return Info(); } - virtual CoSimIO::ControlSignal RecvControlSignalDetail(std::string& rIdentifier) + + virtual Info ExportInfoImpl(const Info& I_Info) { - CO_SIM_IO_ERROR << "RecvControlSignalDetail not implemented for this comm-type" << std::endl; - return CoSimIO::ControlSignal::Dummy; + CO_SIM_IO_ERROR << "ExportInfo not implemented for this comm-type" << std::endl; + return Info(); } - virtual void ImportDataImpl( - const std::string& rIdentifier, - CoSimIO::Internals::DataContainer& rData) + virtual Info ImportDataImpl( + const Info& I_Info, + Internals::DataContainer& rData) { CO_SIM_IO_ERROR << "ImportDataImpl not implemented for this comm-type!" << std::endl; + return Info(); } - virtual void ExportDataImpl( - const std::string& rIdentifier, - const CoSimIO::Internals::DataContainer& rData) + virtual Info ExportDataImpl( + const Info& I_Info, + const Internals::DataContainer& rData) { CO_SIM_IO_ERROR << "ExportDataImpl not implemented for this comm-type!" << std::endl; + return Info(); } - virtual void ImportMeshImpl( - const std::string& rIdentifier, - CoSimIO::Internals::DataContainer& rNodalCoordinates, - CoSimIO::Internals::DataContainer& rElementConnectivities, - CoSimIO::Internals::DataContainer& rElementTypes) + virtual Info ImportMeshImpl( + const Info& I_Info, + ModelPart& O_ModelPart) { - CO_SIM_IO_ERROR << "ImportDataImpl not implemented for this comm-type!" << std::endl; + CO_SIM_IO_ERROR << "ImportMeshImpl not implemented for this comm-type!" << std::endl; + return Info(); } - virtual void ExportMeshImpl( - const std::string& rIdentifier, - const CoSimIO::Internals::DataContainer& rNodalCoordinates, - const CoSimIO::Internals::DataContainer& rElementConnectivities, - const CoSimIO::Internals::DataContainer& rElementTypes) + virtual Info ExportMeshImpl( + const Info& I_Info, + const ModelPart& I_ModelPart) { - CO_SIM_IO_ERROR << "ImportDataImpl not implemented for this comm-type!" << std::endl; + CO_SIM_IO_ERROR << "ExportMeshImpl not implemented for this comm-type!" << std::endl; + return Info(); } - void CheckConnection() + void PerformCompatibilityCheck() { - CO_SIM_IO_ERROR_IF_NOT(mIsConnected) << "No active connection exists!" << std::endl;; + CoSimIO::Info my_info; + CoSimIO::Info partner_info; + my_info.Set("version_major", GetMajorVersion()); + my_info.Set("version_minor", GetMinorVersion()); + my_info.Set("version_patch", GetPatchVersion()); + my_info.Set("primary_was_explicitly_specified", mPrimaryWasExplicitlySpecified); + + my_info.Set("identifier", "compatibility_checks"); + + if (GetIsPrimaryConnection()) { + ExportInfo(my_info); + CoSimIO::Info partner_import_info; + partner_import_info.Set("identifier", "compatibility_checks"); + partner_info = ImportInfo(partner_import_info); + } else { + CoSimIO::Info partner_import_info; + partner_import_info.Set("identifier", "compatibility_checks"); + partner_info = ImportInfo(partner_import_info); + ExportInfo(my_info); + } + + // perform checks for compatibility + CO_SIM_IO_ERROR_IF(GetMajorVersion() != partner_info.Get("version_major")) << "Major version mismatch! My version: " << GetMajorVersion() << "; partner version: " << partner_info.Get("version_major") << std::endl; + CO_SIM_IO_ERROR_IF(GetMinorVersion() != partner_info.Get("version_minor")) << "Minor version mismatch! My version: " << GetMinorVersion() << "; partner version: " << partner_info.Get("version_minor") << std::endl; + CO_SIM_IO_ERROR_IF(mPrimaryWasExplicitlySpecified != partner_info.Get("primary_was_explicitly_specified")) << std::boolalpha << "Mismatch in how the primary connection was specified!\nPrimary connection was explicitly specified for me: " << mPrimaryWasExplicitlySpecified << "\nPrimary connection was explicitly specified for partner: " << partner_info.Get("primary_was_explicitly_specified") << std::endl; } }; } // namespace Internals } // namespace CoSimIO -#endif // CO_SIM_IO_COMMUNICATION_H_INCLUDED +#endif // CO_SIM_IO_COMMUNICATION_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/file_communication.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/file_communication.hpp index ac3e97153b04..a403f2b07848 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/file_communication.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/file_communication.hpp @@ -10,85 +10,31 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_FILE_COMMUNICATION_H_INCLUDED -#define CO_SIM_IO_FILE_COMMUNICATION_H_INCLUDED +#ifndef CO_SIM_IO_FILE_COMMUNICATION_INCLUDED +#define CO_SIM_IO_FILE_COMMUNICATION_INCLUDED // System includes #include #include #include #include - -// std::filesystem is needed for file communication in a folder -// std::filesystem is part of C++17 and not supported by every compiler. Here we check if it is available. -#if defined(__cplusplus) && __cplusplus >= 201703L - #if defined(__has_include) && __has_include() // has_include is C++17, hence has to be checked in a separate line - #define CO_SIM_IO_FILESYSTEM_AVAILABLE - #include - namespace fs = std::filesystem; - #elif __has_include() - #define CO_SIM_IO_FILESYSTEM_AVAILABLE - #include - namespace fs = std::experimental::filesystem; - #endif -#endif - +#include +#include // Project includes #include "communication.hpp" +#include "../vtk_utilities.hpp" +#include "../filesystem_inc.hpp" namespace CoSimIO { namespace Internals { namespace { // helpers namespace -static double ElapsedSeconds(const std::chrono::steady_clock::time_point& rStartTime) -{ - using namespace std::chrono; - return duration_cast>(steady_clock::now() - rStartTime).count(); -} - -static bool FileExists(const std::string& rFileName) -{ - std::ifstream infile(rFileName); - return infile.good(); // no need to close manually -} - -static void RemoveFile(const std::string& rFileName) -{ - if (std::remove(rFileName.c_str()) != 0) { - CO_SIM_IO_INFO("CoSimIO") << "Warning: \"" << rFileName << "\" could not be deleted!" << std::endl; - } -} - template -static void CheckStream(const T& rStream, const std::string& rFileName) +static void CheckStream(const T& rStream, const fs::path& rPath) { - CO_SIM_IO_ERROR_IF_NOT(rStream.is_open()) << rFileName << " could not be opened!" << std::endl; -} - -static int GetNumNodesForVtkCellType(const int VtkCellType) -{ - const std::unordered_map vtk_cell_type_map { - { /*Point3D, */ 1 , 1}, - { /*Line3D2, */ 3 , 2}, - { /*Triangle3D3, */ 5 , 3}, - { /*Quadrilateral3D4, */ 9 , 4}, - { /*Tetrahedra3D4, */ 10 , 4}, - { /*Hexahedra3D8, */ 12 , 8}, - { /*Prism3D6, */ 13 , 6}, - { /*Line3D3, */ 21 , 3}, - { /*Triangle3D6, */ 22 , 6}, - { /*Quadrilateral3D8, */ 23 , 7}, - { /*Tetrahedra3D10, */ 24, 10} - }; - - if (vtk_cell_type_map.count(VtkCellType) > 0) { - return vtk_cell_type_map.at(VtkCellType); - } else { - CO_SIM_IO_ERROR << "Unsupported cell type: " << VtkCellType << std::endl; - return 0; - } + CO_SIM_IO_ERROR_IF_NOT(rStream.is_open()) << rPath << " could not be opened!" << std::endl; } } // helpers namespace @@ -97,61 +43,161 @@ static int GetNumNodesForVtkCellType(const int VtkCellType) class FileCommunication : public Communication { public: - explicit FileCommunication(const std::string& rName, const Info& I_Settings, const bool IsConnectionMaster) - : Communication(rName, I_Settings, IsConnectionMaster) + explicit FileCommunication(const Info& I_Settings) : Communication(I_Settings) { - if (I_Settings.Has("use_folder_for_communication")) { - mCommInFolder = I_Settings.Get("use_folder_for_communication"); + mCommFolder = GetWorkingDirectory(); + mCommFolder /= ".CoSimIOFileComm_" + GetConnectionName(); + mCommInFolder = I_Settings.Get("use_folder_for_communication", true); + } + + ~FileCommunication() override + { + if (GetIsConnected()) { + CO_SIM_IO_INFO("CoSimIO") << "Warning: Disconnect was not performed, attempting automatic disconnection!" << std::endl; + Info tmp; + Disconnect(tmp); } + } - mCommFolder = ".CoSimIOFileComm_"+rName; +private: - #ifndef CO_SIM_IO_FILESYSTEM_AVAILABLE - CO_SIM_IO_ERROR_IF(mCommInFolder) << "Communication is a folder can only be used if std::filesystem (C++17) is available" << std::endl; - #endif + fs::path mCommFolder; + bool mCommInFolder = true; + mutable int mFileIndex = 0; - if (mCommInFolder && GetIsConnectionMaster()) { - #ifdef CO_SIM_IO_FILESYSTEM_AVAILABLE - // delete and recreate directory to remove potential leftovers - fs::remove_all(mCommFolder); - fs::create_directory(mCommFolder); - #endif + Info ConnectDetail(const Info& I_Info) override + { + if (mCommInFolder) { + if (GetIsPrimaryConnection()) { + // delete and recreate directory to remove potential leftovers + std::error_code ec; + fs::remove_all(mCommFolder, ec); + if (ec) { + CO_SIM_IO_INFO("CoSimIO") << "Warning, communication directory (" << mCommFolder << ")could not be deleted!\nError code: " << ec.message() << std::endl; + } + if (!fs::exists(mCommFolder)) { + fs::create_directory(mCommFolder); + } + } } + + ExchangeSyncFileWithPartner("connect"); + + Info info; + info.Set("is_connected", true); + return info; } - ~FileCommunication() override + Info DisconnectDetail(const Info& I_Info) override { - if (GetIsConnected()) { - CO_SIM_IO_INFO("CoSimIO") << "Warning: Disconnect was not performed, attempting automatic disconnection!" << std::endl; - Disconnect(); + ExchangeSyncFileWithPartner("disconnect"); + + if (mCommInFolder && GetIsPrimaryConnection()) { + // delete directory to remove potential leftovers + std::error_code ec; + fs::remove_all(mCommFolder, ec); + if (ec) { + CO_SIM_IO_INFO("CoSimIO") << "Warning, communication directory (" << mCommFolder << ")could not be deleted!\nError code: " << ec.message() << std::endl; + } } + + Info info; + info.Set("is_connected", false); + return info; } -private: + void ExchangeSyncFileWithPartner(const std::string& rIdentifier) const + { + const fs::path file_name_primary(GetFileName("CoSimIO_primary_" + rIdentifier + "_" + GetConnectionName(), "sync")); + const fs::path file_name_secondary(GetFileName("CoSimIO_secondary_" + rIdentifier + "_" + GetConnectionName(), "sync")); + + if (GetIsPrimaryConnection()) { + std::ofstream sync_file; + sync_file.open(GetTempFileName(file_name_primary)); + sync_file.close(); + CO_SIM_IO_ERROR_IF_NOT(fs::exists(GetTempFileName(file_name_primary))) << "Primary sync file " << file_name_primary << " could not be created!" << std::endl; + MakeFileVisible(file_name_primary); - std::string mCommFolder = ""; - bool mCommInFolder = false; + WaitForPath(file_name_secondary); + RemovePath(file_name_secondary); - bool ConnectDetail() override + WaitUntilFileIsRemoved(file_name_primary); + } else { + WaitForPath(file_name_primary); + RemovePath(file_name_primary); + + std::ofstream sync_file; + sync_file.open(GetTempFileName(file_name_secondary)); + sync_file.close(); + CO_SIM_IO_ERROR_IF_NOT(fs::exists(GetTempFileName(file_name_secondary))) << "Secondary sync file " << file_name_secondary << " could not be created!" << std::endl; + MakeFileVisible(file_name_secondary); + + WaitUntilFileIsRemoved(file_name_secondary); + } + } + + Info ImportInfoImpl(const Info& I_Info) override { - return true; // nothing needed here for file-based communication (maybe do sth here?) - // master could write a file that gets deleted by slave to aknowledge connection... Probably not a bad idea! => slave returns once it found and deleted file, master waits for deletion of file + const std::string identifier = I_Info.Get("identifier"); + CheckEntry(identifier, "identifier"); + + const fs::path file_name(GetFileName("CoSimIO_info_" + GetConnectionName() + "_" + identifier, "dat")); + + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to import Info in file " << file_name << " ..." << std::endl; + + WaitForPath(file_name); + + std::ifstream input_file(file_name); + CheckStream(input_file, file_name); + + Info imported_info; + imported_info.Load(input_file); + + input_file.close(); // TODO check return value? + RemovePath(file_name); + + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished importing Info" << std::endl; + + return imported_info; } - bool DisconnectDetail() override + Info ExportInfoImpl(const Info& I_Info) override { - return true; // nothing needed here for file-based communication (maybe do sth here?) + const std::string identifier = I_Info.Get("identifier"); + CheckEntry(identifier, "identifier"); + + const fs::path file_name(GetFileName("CoSimIO_info_" + GetConnectionName() + "_" + identifier, "dat")); + + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to export Info in file " << file_name << " ..." << std::endl; + + WaitUntilFileIsRemoved(file_name); // TODO maybe this can be queued somehow ... => then it would not block the sender + + std::ofstream output_file; + output_file.open(GetTempFileName(file_name)); + CheckStream(output_file, file_name); + + I_Info.Save(output_file); + + output_file.close(); + MakeFileVisible(file_name); + + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished exporting Info" << std::endl; + + return Info(); // TODO use } - void ImportDataImpl( - const std::string& rIdentifier, - CoSimIO::Internals::DataContainer& rData) override + Info ImportDataImpl( + const Info& I_Info, + Internals::DataContainer& rData) override { - const std::string file_name(GetFullPath("CoSimIO_data_" + GetConnectionName() + "_" + rIdentifier + ".dat")); + const std::string identifier = I_Info.Get("identifier"); + CheckEntry(identifier, "identifier"); + + const fs::path file_name(GetFileName("CoSimIO_data_" + GetConnectionName() + "_" + identifier, "dat")); - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to receive array \"" << rIdentifier << "\" in file \"" << file_name << "\" ..." << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to import array \"" << identifier << "\" in file " << file_name << " ..." << std::endl; - WaitForFile(file_name); + WaitForPath(file_name); const auto start_time(std::chrono::steady_clock::now()); @@ -169,23 +215,29 @@ class FileCommunication : public Communication input_file >> rData[i]; } - RemoveFile(file_name); + input_file.close(); + RemovePath(file_name); - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished receiving array with size: " << size_read << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished importing array with size: " << size_read << std::endl; - CO_SIM_IO_INFO_IF("CoSimIO", GetPrintTiming()) << "Receiving Array \"" << rIdentifier << "\" took: " << ElapsedSeconds(start_time) << " [sec]" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetPrintTiming()) << "Importing Array \"" << identifier << "\" took: " << ElapsedSeconds(start_time) << " [sec]" << std::endl; + + return Info(); // TODO use } - void ExportDataImpl( - const std::string& rIdentifier, - const CoSimIO::Internals::DataContainer& rData) override + Info ExportDataImpl( + const Info& I_Info, + const Internals::DataContainer& rData) override { - const std::string file_name(GetFullPath("CoSimIO_data_" + GetConnectionName() + "_" + rIdentifier + ".dat")); + const std::string identifier = I_Info.Get("identifier"); + CheckEntry(identifier, "identifier"); + + const fs::path file_name(GetFileName("CoSimIO_data_" + GetConnectionName() + "_" + identifier, "dat")); WaitUntilFileIsRemoved(file_name); // TODO maybe this can be queued somehow ... => then it would not block the sender const std::size_t size = rData.size(); - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to send array \"" << rIdentifier << "\" with size: " << size << " in file \"" << file_name << "\" ..." << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to export array \"" << identifier << "\" with size: " << size << " in file " << file_name << " ..." << std::endl; const auto start_time(std::chrono::steady_clock::now()); @@ -206,22 +258,25 @@ class FileCommunication : public Communication output_file.close(); MakeFileVisible(file_name); - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished sending array" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished exporting array" << std::endl; - CO_SIM_IO_INFO_IF("CoSimIO", GetPrintTiming()) << "Sending Array \"" << rIdentifier << "\" took: " << ElapsedSeconds(start_time) << " [sec]" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetPrintTiming()) << "Exporting Array \"" << identifier << "\" took: " << ElapsedSeconds(start_time) << " [sec]" << std::endl; + + return Info(); // TODO use } - void ImportMeshImpl( - const std::string& rIdentifier, - CoSimIO::Internals::DataContainer& rNodalCoordinates, - CoSimIO::Internals::DataContainer& rElementConnectivities, - CoSimIO::Internals::DataContainer& rElementTypes) override + Info ImportMeshImpl( + const Info& I_Info, + ModelPart& O_ModelPart) override { - const std::string file_name(GetFullPath("CoSimIO_mesh_" + GetConnectionName() + "_" + rIdentifier + ".vtk")); + const std::string identifier = I_Info.Get("identifier"); + CheckEntry(identifier, "identifier"); + + const fs::path file_name(GetFileName("CoSimIO_mesh_" + GetConnectionName() + "_" + identifier, "vtk")); - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to receive mesh \"" << rIdentifier << "\" in file \"" << file_name << "\" ..." << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to import mesh \"" << identifier << "\" in file " << file_name << " ..." << std::endl; - WaitForFile(file_name); + WaitForPath(file_name); const auto start_time(std::chrono::steady_clock::now()); @@ -230,90 +285,116 @@ class FileCommunication : public Communication // reading file std::string current_line; - bool nodes_read = false; - bool cells_read = false; + std::vector nodal_coords; + std::vector nodal_ids; + std::vector element_ids; + std::vector element_types; + std::vector element_connectivities; while (std::getline(input_file, current_line)) { // reading nodes if (current_line.find("POINTS") != std::string::npos) { - CO_SIM_IO_ERROR_IF(nodes_read) << "The nodes were read already!" << std::endl; - CO_SIM_IO_ERROR_IF(cells_read) << "The cells were read already!" << std::endl; - nodes_read = true; - - int num_nodes; + std::size_t num_nodes; current_line = current_line.substr(current_line.find("POINTS") + 7); // removing "POINTS" std::istringstream line_stream(current_line); line_stream >> num_nodes; CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Mesh contains " << num_nodes << " Nodes" << std::endl; - rNodalCoordinates.resize(3*num_nodes); + nodal_coords.resize(3*num_nodes); + nodal_ids.resize(num_nodes); - for (int i=0; i> rNodalCoordinates[i]; + for (std::size_t i=0; i> nodal_coords[i]; } } - // reading cells + // reading connectivities if (current_line.find("CELLS") != std::string::npos) { - CO_SIM_IO_ERROR_IF_NOT(nodes_read) << "The nodes were not yet read!" << std::endl; - CO_SIM_IO_ERROR_IF(cells_read) << "The cells were read already!" << std::endl; - cells_read = true; - - int num_nodes_per_cell, num_cells, elem_conn, cell_list_size; + std::size_t num_elems, num_nodes_per_elem; current_line = current_line.substr(current_line.find("CELLS") + 6); // removing "CELLS" std::istringstream line_stream(current_line); - line_stream >> num_cells; - line_stream >> cell_list_size; + line_stream >> num_elems; - rElementConnectivities.resize(cell_list_size-num_cells); // the first in number in each line is the number of connectivities, which is not needed bcs it can be derived form the elements-type - rElementTypes.resize(num_cells); + element_ids.resize(num_elems); + element_types.resize(num_elems); + element_connectivities.resize(num_elems); - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Mesh contains " << num_cells << " Elements" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Mesh contains " << num_elems << " Elements" << std::endl; - int counter=0; - for (int i=0; i> num_nodes_per_cell; - for (int j=0; j> elem_conn; - rElementConnectivities[counter++] = elem_conn; + for (std::size_t i=0; i> num_nodes_per_elem; + element_connectivities[i].resize(num_nodes_per_elem); + for (std::size_t j=0; j> element_connectivities[i][j]; } } } - // reading cell types - if (current_line.find("CELL_TYPES") != std::string::npos) { - CO_SIM_IO_ERROR_IF_NOT(nodes_read) << "The nodes were not yet read!" << std::endl; - CO_SIM_IO_ERROR_IF_NOT(cells_read) << "The cells were not yet read!" << std::endl; + // reading node Ids + if (current_line.find("NODE_ID") != std::string::npos) { + for (std::size_t i=0; i> nodal_ids[i]; + } + } - for (std::size_t i=0; i> rElementTypes[i]; + // reading element Ids + if (current_line.find("ELEMENT_ID") != std::string::npos) { + for (std::size_t i=0; i> element_ids[i]; } + } + + // reading element types + if (current_line.find("ELEMENT_TYPE") != std::string::npos) { + int enum_temp; + for (std::size_t i=0; i> enum_temp; // using a temp variable as enums cannot be read directly + element_types[i] = static_cast(enum_temp); + } + } + } + // filling ModelPart with read information + for (std::size_t i=0; i1) << "Finished receiving mesh" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished importing mesh" << std::endl; - CO_SIM_IO_INFO_IF("CoSimIO", GetPrintTiming()) << "Receiving Mesh \"" << file_name << "\" took: " << ElapsedSeconds(start_time) << " [sec]" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetPrintTiming()) << "Importing Mesh \"" << identifier << "\" took: " << ElapsedSeconds(start_time) << " [sec]" << std::endl; + + return Info(); // TODO use } - void ExportMeshImpl( - const std::string& rIdentifier, - const CoSimIO::Internals::DataContainer& rNodalCoordinates, - const CoSimIO::Internals::DataContainer& rElementConnectivities, - const CoSimIO::Internals::DataContainer& rElementTypes) override + Info ExportMeshImpl( + const Info& I_Info, + const ModelPart& I_ModelPart) override { - const std::string file_name(GetFullPath("CoSimIO_mesh_" + GetConnectionName() + "_" + rIdentifier + ".vtk")); + const std::string identifier = I_Info.Get("identifier"); + CheckEntry(identifier, "identifier"); - WaitUntilFileIsRemoved(file_name); // TODO maybe this can be queued somehow ... => then it would not block the sender + const fs::path file_name(GetFileName("CoSimIO_mesh_" + GetConnectionName() + "_" + identifier, "vtk")); - const std::size_t num_nodes = rNodalCoordinates.size()/3; - const std::size_t num_elems = rElementTypes.size(); + WaitUntilFileIsRemoved(file_name); // TODO maybe this can be queued somehow ... => then it would not block the sender - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to send mesh \"" << rIdentifier << "\" with " << num_nodes << " Nodes | " << num_elems << " Elements in file \"" << file_name << "\" ..." << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to export mesh \"" << identifier << "\" with " << I_ModelPart.NumberOfNodes() << " Nodes | " << I_ModelPart.NumberOfElements() << " Elements in file " << file_name << " ..." << std::endl; const auto start_time(std::chrono::steady_clock::now()); @@ -325,149 +406,147 @@ class FileCommunication : public Communication // write file header output_file << "# vtk DataFile Version 4.0\n"; - output_file << "vtk output\n"; + output_file << "CoSimIO FileCommunication\n"; output_file << "ASCII\n"; output_file << "DATASET UNSTRUCTURED_GRID\n\n"; - // write nodes - output_file << "POINTS " << num_nodes << " float\n"; - for (std::size_t i=0; i id_map; + IdType vtk_id = 0; + output_file << "POINTS " << I_ModelPart.NumberOfNodes() << " float\n"; + for (auto node_it=I_ModelPart.NodesBegin(); node_it!=I_ModelPart.NodesEnd(); ++node_it) { + output_file << (*node_it)->X() << " " << (*node_it)->Y() << " " << (*node_it)->Z() << "\n"; + id_map[(*node_it)->Id()] = vtk_id++; } output_file << "\n"; - // get connectivity information + // get cells size information std::size_t cell_list_size = 0; - std::size_t counter = 0; - int connectivities_offset = std::numeric_limits::max(); //in paraview the connectivities start from 0, hence we have to check beforehand what is the connectivities offset - for (std::size_t i=0; iNumberOfNodes() + 1; // +1 for size of connectivity } - CO_SIM_IO_ERROR_IF(num_elems > 0 && connectivities_offset != 0) << "Connectivities have an offset of " << connectivities_offset << " which is not allowed!" << std::endl; - // write cells connectivity - counter = 0; - output_file << "CELLS " << num_elems << " " << cell_list_size << "\n"; - for (std::size_t i=0; iNumberOfNodes(); output_file << num_nodes_cell << " "; - for (std::size_t j=0; jNodesBegin(); node_it!=(*elem_it)->NodesEnd(); ++node_it) { + const IdType node_id = (*node_it)->Id(); + auto id_iter = const_id_map.find(node_id); + CO_SIM_IO_ERROR_IF(id_iter == const_id_map.end()) << "The node with Id " << node_id << " is not part of the ModelPart but used for Element with Id " << (*elem_it)->Id() << std::endl; + output_file << id_iter->second; + if (node_counter++(GetVtkCellTypeForElementType((*elem_it)->Type())) << "\n"; } + output_file << "\n"; - output_file.close(); - MakeFileVisible(file_name); - - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished sending mesh" << std::endl; - - CO_SIM_IO_INFO_IF("CoSimIO", GetPrintTiming()) << "Sending Mesh \"" << rIdentifier << "\" took: " << ElapsedSeconds(start_time) << " [sec]" << std::endl; - } - - void SendControlSignalDetail(const std::string& rIdentifier, const CoSimIO::ControlSignal Signal) override - { - const std::string file_name(GetFullPath("CoSimIO_control_signal_" + GetConnectionName() + ".dat")); - - WaitUntilFileIsRemoved(file_name); // TODO maybe this can be queued somehow ... => then it would not block the sender - - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to send control signal in file \"" << file_name << "\" ..." << std::endl; + // writing node Ids + output_file << "POINT_DATA " << I_ModelPart.NumberOfNodes() << "\n"; + output_file << "FIELD FieldData 1" << "\n"; + output_file << "NODE_ID 1 " << I_ModelPart.NumberOfNodes() << " int\n"; + for (auto node_it=I_ModelPart.NodesBegin(); node_it!=I_ModelPart.NodesEnd(); ++node_it) { + output_file << (*node_it)->Id() << "\n"; + } + output_file << "\n"; - std::ofstream output_file; - output_file.open(GetTempFileName(file_name)); - CheckStream(output_file, file_name); + // writing element Ids + output_file << "CELL_DATA " << I_ModelPart.NumberOfElements() << "\n"; + output_file << "FIELD FieldData 1" << "\n"; + output_file << "ELEMENT_ID 1 " << I_ModelPart.NumberOfElements() << " int\n"; + for (auto elem_it=I_ModelPart.ElementsBegin(); elem_it!=I_ModelPart.ElementsEnd(); ++elem_it) { + output_file << (*elem_it)->Id() << "\n"; + } + output_file << "\n"; - output_file << static_cast(Signal) << " " << rIdentifier; + // writing element types + output_file << "CELL_DATA " << I_ModelPart.NumberOfElements() << "\n"; + output_file << "FIELD FieldData 1" << "\n"; + output_file << "ELEMENT_TYPE 1 " << I_ModelPart.NumberOfElements() << " int\n"; + for (auto elem_it=I_ModelPart.ElementsBegin(); elem_it!=I_ModelPart.ElementsEnd(); ++elem_it) { + output_file << static_cast((*elem_it)->Type()) << "\n"; + } output_file.close(); MakeFileVisible(file_name); - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished sending control signal" << std::endl; - } - - CoSimIO::ControlSignal RecvControlSignalDetail(std::string& rIdentifier) override - { - const std::string file_name(GetFullPath("CoSimIO_control_signal_" + GetConnectionName() + ".dat")); - - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Attempting to receive control signal in file \"" << file_name << "\" ..." << std::endl; - - WaitForFile(file_name); - - std::ifstream input_file(file_name); - CheckStream(input_file, file_name); + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished exporting mesh" << std::endl; - int control_signal; - input_file >> control_signal; - input_file >> rIdentifier; + CO_SIM_IO_INFO_IF("CoSimIO", GetPrintTiming()) << "Exporting Mesh \"" << identifier << "\" took: " << ElapsedSeconds(start_time) << " [sec]" << std::endl; - RemoveFile(file_name); - - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>1) << "Finished receiving control signal" << std::endl; - - return static_cast(control_signal); + return Info(); // TODO use } - std::string GetTempFileName(const std::string& rFileName) + fs::path GetTempFileName(const fs::path& rPath) const { if (mCommInFolder) { - // TODO check this - return std::string(rFileName).insert(mCommFolder.length()+1, "."); + return rPath.string().insert(mCommFolder.string().length()+1, "."); } else { - return "." + rFileName; + return "." + rPath.string(); } } - std::string GetFullPath(const std::string& rFileName) + fs::path GetFileName(const fs::path& rPath, const std::string& rExtension) const { + fs::path local_copy(rPath); + local_copy += "_" + std::to_string((mFileIndex++)%100) + "." + rExtension; + if (mCommInFolder) { - // TODO check this - return mCommFolder + "/" + rFileName; // using portable separator "/" + return mCommFolder / local_copy; } else { - return rFileName; + return local_copy; } } - void WaitForFile(const std::string& rFileName) + void WaitForPath(const fs::path& rPath) const { - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Waiting for file: \"" << rFileName << "\"" << std::endl; - while(!FileExists(rFileName)) { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); // wait 0.05s before next check - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>2) << " Waiting" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Waiting for: " << rPath << std::endl; + while(!fs::exists(rPath)) { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); // wait 0.001s before next check } - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Found file: \"" << rFileName << "\"" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Found: " << rPath << std::endl; } - void WaitUntilFileIsRemoved(const std::string& rFileName) + void WaitUntilFileIsRemoved(const fs::path& rPath) const { - if (FileExists(rFileName)) { // only issue the wating message if the file exists initially - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Waiting for file: \"" << rFileName << "\" to be removed" << std::endl; - while(FileExists(rFileName)) { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); // wait 0.05s before next check - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>2) << " Waiting" << std::endl; + if (fs::exists(rPath)) { // only issue the wating message if the file exists initially + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "Waiting for: " << rPath << " to be removed" << std::endl; + while(fs::exists(rPath)) { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); // wait 0.001s before next check } - CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << "File: \"" << rFileName << "\" was removed" << std::endl; + CO_SIM_IO_INFO_IF("CoSimIO", GetEchoLevel()>0) << rPath << " was removed" << std::endl; } } - void MakeFileVisible(const std::string& rFinalFileName) + void MakeFileVisible(const fs::path& rPath) const { - if (std::rename(GetTempFileName(rFinalFileName).c_str(), rFinalFileName.c_str()) != 0) { - CO_SIM_IO_INFO("CoSimIO") << "Warning: \"" << rFinalFileName << "\" could not be made visible!" << std::endl; + std::error_code ec; + fs::rename(GetTempFileName(rPath), rPath, ec); + CO_SIM_IO_ERROR_IF(ec) << rPath << " could not be made visible!\nError code: " << ec.message() << std::endl; + } + + void RemovePath(const fs::path& rPath) const + { + // In windows the file cannot be removed if another file handle is using it + // this can be the case here if the partner checks if the file (still) exists + // hence we try multiple times to delete it + std::error_code ec; + for (std::size_t i=0; i<5; ++i) { + if (fs::remove(rPath, ec)) { + return; // if file could be removed succesfully then return + } } + CO_SIM_IO_ERROR << rPath << " could not be deleted!\nError code: " << ec.message() << std::endl; } }; @@ -475,4 +554,4 @@ class FileCommunication : public Communication } // namespace Internals } // namespace CoSimIO -#endif // CO_SIM_IO_FILE_COMMUNICATION_H_INCLUDED \ No newline at end of file +#endif // CO_SIM_IO_FILE_COMMUNICATION_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/mpi_communication.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/mpi_communication.hpp index 4f25ba4d4fd3..e7987bbb8305 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/mpi_communication.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/mpi_communication.hpp @@ -10,8 +10,8 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_MPI_COMMUNICATION_H_INCLUDED -#define CO_SIM_IO_MPI_COMMUNICATION_H_INCLUDED +#ifndef CO_SIM_IO_MPI_COMMUNICATION_INCLUDED +#define CO_SIM_IO_MPI_COMMUNICATION_INCLUDED // System includes #include "mpi.h" @@ -25,8 +25,7 @@ namespace Internals { class MPICommunication : public Communication { public: - explicit MPICommunication(const std::string& rName, SettingsType& rSettings, const bool IsConnectionMaster) - : Communication(rName, rSettings, IsConnectionMaster) + explicit MPICommunication(const Info& I_Settings) : Communication(I_Settings) { static_assert(false,"MPI Communication is not implemented yet"); /* @@ -41,4 +40,4 @@ class MPICommunication : public Communication } // namespace Internals } // namespace CoSimIO -#endif // CO_SIM_IO_MPI_COMMUNICATION_H_INCLUDED +#endif // CO_SIM_IO_MPI_COMMUNICATION_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/sockets_communication.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/sockets_communication.hpp index cb53ad71edca..d1b613ee99ba 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/sockets_communication.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/communication/sockets_communication.hpp @@ -10,8 +10,8 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_SOCKETS_COMMUNICATION_H_INCLUDED -#define CO_SIM_IO_SOCKETS_COMMUNICATION_H_INCLUDED +#ifndef CO_SIM_IO_SOCKETS_COMMUNICATION_INCLUDED +#define CO_SIM_IO_SOCKETS_COMMUNICATION_INCLUDED // System includes @@ -27,8 +27,7 @@ namespace Internals { class SocketsCommunication : public Communication { public: - explicit SocketsCommunication(const std::string& rName, SettingsType& rSettings, const bool IsConnectionMaster) - : Communication(rName, rSettings, IsConnectionMaster) + explicit SocketsCommunication(const Info& I_Settings) : Communication(I_Settings) { static_assert(false,"Sockets Communication is not implemented yet"); } @@ -37,4 +36,4 @@ class SocketsCommunication : public Communication } // namespace Internals } // namespace CoSimIO -#endif // CO_SIM_IO_SOCKETS_COMMUNICATION_H_INCLUDED +#endif // CO_SIM_IO_SOCKETS_COMMUNICATION_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/connection.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/connection.hpp index 23b41d2f5539..da052f8adb7f 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/connection.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/connection.hpp @@ -10,8 +10,8 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_CONNECTION_H_INCLUDED -#define CO_SIM_IO_CONNECTION_H_INCLUDED +#ifndef CO_SIM_IO_CONNECTION_INCLUDED +#define CO_SIM_IO_CONNECTION_INCLUDED // Optional includes #ifdef CO_SIM_IO_USING_SOCKETS @@ -45,43 +45,32 @@ class Connection using FunctionPointerType = std::function; - explicit Connection(const std::string& rName, const Info& I_Settings) : mConnectionName(rName) + explicit Connection(const Info& I_Settings) { Initialize(I_Settings); } - Info Connect() + Info Connect(const Info& I_Info) { - /*const bool is_connected = */mpComm->Connect(); - Info info; // TODO in the future probably it makes more sense that the mpComm can directly return the Info to potentionally populate it e.g. with error codes + Info info = mpComm->Connect(I_Info); info.Set("connection_status", ConnectionStatus::Connected); return info; } - Info Disconnect() + Info Disconnect(const Info& I_Info) { - /*const bool is_disconnected = */mpComm->Disconnect(); - Info info; // TODO in the future probably it makes more sense that the mpComm can directly return the Info to potentionally populate it e.g. with error codes + Info info = mpComm->Disconnect(I_Info); info.Set("connection_status", ConnectionStatus::Disconnected); return info; } - Info SendControlSignal(const std::string& rIdentifier, const CoSimIO::ControlSignal Signal) - { - CO_SIM_IO_ERROR_IF_NOT(mIsConnectionMaster) << "This function can only be called as the Connection-Master!" << std::endl; - mpComm->SendControlSignal(rIdentifier, Signal); - return Info(); // TODO use this - } - Info Register( const std::string& rFunctionName, FunctionPointerType FunctionPointer) { CO_SIM_IO_INFO("CoSimIO") << "Registering function for: " << rFunctionName << std::endl; - CO_SIM_IO_ERROR_IF(mIsConnectionMaster) << "This function can only be called as the Connection-Slave!" << std::endl; - - CheckIfFunctionNameIsValid(rFunctionName); + CheckIfNameIsValid(rFunctionName); CO_SIM_IO_ERROR_IF((mRegisteredFunctions.count(rFunctionName)>0)) << "A function was already registered for " << rFunctionName << "!" << std::endl; @@ -89,117 +78,93 @@ class Connection return Info(); // TODO use this } - Info Run() + Info Run(const Info& I_Info) { - CO_SIM_IO_ERROR_IF(mIsConnectionMaster) << "This function can only be called as the Connection-Slave!" << std::endl; + CoSimIO::Info ctrl_info; + ctrl_info.Set("identifier", "run_control"); - CoSimIO::ControlSignal control_signal; - std::string identifier; while(true) { - control_signal = RecvControlSignal(identifier); - //TODO check if received signal is valid - if (control_signal == CoSimIO::ControlSignal::BreakSolutionLoop) { - break; // coupled simulation is done + auto info = ImportInfo(ctrl_info); + const std::string control_signal = info.Get("control_signal"); + CheckIfNameIsValid(control_signal); + if (control_signal == "exit") { + break; } else { - const std::string function_name(ControlSignalName(control_signal)); - CO_SIM_IO_ERROR_IF_NOT((mRegisteredFunctions.count(function_name)>0)) << "No function was registered for \"" << function_name << "\"!" << std::endl; + auto it_fct = mRegisteredFunctions.find(control_signal); + if (it_fct == mRegisteredFunctions.end()) { + std::stringstream err_msg; + err_msg << "Nothing was registered for \"" << control_signal << "\"!\nOnly the following names are currently registered:"; + for (const auto& reg : mRegisteredFunctions) { + err_msg << "\n " << reg.first; + } + err_msg << "\n end" << std::endl; + CO_SIM_IO_ERROR << err_msg.str(); + } Info info; - mRegisteredFunctions.at(function_name)(info); + it_fct->second(info); } } return Info(); // TODO use this } - bool IsConverged() - { - std::string dummy(""); - return (RecvControlSignal(dummy) == CoSimIO::ControlSignal::ConvergenceAchieved); - } - template - Info ImportData(Args&&... args) + Info ImportInfo(Args&&... args) { - mpComm->ImportData(std::forward(args)...); - - return Info(); // TODO use this + return mpComm->ImportInfo(std::forward(args)...); } template - Info ExportData(Args&&... args) + Info ExportInfo(Args&&... args) { - mpComm->ExportData(std::forward(args)...); - - return Info(); // TODO use this + return mpComm->ExportInfo(std::forward(args)...); } - template - Info ImportMesh(Args&&... args) + Info ImportData(Args&&... args) { - mpComm->ImportMesh(std::forward(args)...); - - return Info(); // TODO use this + return mpComm->ImportData(std::forward(args)...); } template - Info ExportMesh(Args&&... args) + Info ExportData(Args&&... args) { - mpComm->ExportMesh(std::forward(args)...); - - return Info(); // TODO use this + return mpComm->ExportData(std::forward(args)...); } template - Info ImportGeometry(Args&&... args) + Info ImportMesh(Args&&... args) { - CO_SIM_IO_ERROR << "Importing of Geometry is not yet implemented!" << std::endl; - mpComm->ImportGeometry(std::forward(args)...); - - return Info(); // TODO use this + return mpComm->ImportMesh(std::forward(args)...); } template - Info ExportGeometry(Args&&... args) + Info ExportMesh(Args&&... args) { - CO_SIM_IO_ERROR << "Exporting of Geometry is not yet implemented!" << std::endl; - mpComm->ExportGeometry(std::forward(args)...); - - return Info(); // TODO use this + return mpComm->ExportMesh(std::forward(args)...); } private: std::unique_ptr mpComm; // handles communication (File, Sockets, MPI, ...) - std::string mConnectionName; - - bool mIsConnectionMaster = false; - std::unordered_map mRegisteredFunctions; void Initialize(const Info& I_Settings) { - std::string comm_format = "file"; // default is file-communication - if (I_Settings.Has("communication_format")) { // communication format has been specified - comm_format = I_Settings.Get("communication_format"); - } - - if (I_Settings.Has("is_connection_master")) { // is_connection_master has been specified - mIsConnectionMaster = I_Settings.Get("is_connection_master"); - } + const std::string comm_format = I_Settings.Get("communication_format", "file"); // default is file-communication - CO_SIM_IO_INFO("CoSimIO") << "CoSimIO for \"" << mConnectionName << "\" uses communication format: " << comm_format << std::endl; + CO_SIM_IO_INFO("CoSimIO") << "CoSimIO from \"" << I_Settings.Get("my_name") << "\" to \"" << I_Settings.Get("connect_to") << "\" uses communication format: " << comm_format << std::endl; if (comm_format == "file") { - mpComm = std::unique_ptr(new FileCommunication(mConnectionName, I_Settings, mIsConnectionMaster)); + mpComm = CoSimIO::make_unique(I_Settings); } else if (comm_format == "sockets") { #ifdef CO_SIM_IO_USING_SOCKETS - mpComm = std::unique_ptr(new SocketsCommunication(mConnectionName, I_Settings, mIsConnectionMaster)); + mpComm = CoSimIO::make_unique(I_Settings); #else CO_SIM_IO_ERROR << "Support for Sockets was not compiled!" << std::endl; #endif // CO_SIM_IO_USING_SOCKETS } else if (comm_format == "mpi") { #ifdef CO_SIM_IO_USING_MPI - mpComm = std::unique_ptr(new MPICommunication(mConnectionName, I_Settings, mIsConnectionMaster)); + mpComm = CoSimIO::make_unique(I_Settings); #else CO_SIM_IO_ERROR << "Support for MPI was not compiled!" << std::endl; #endif // CO_SIM_IO_USING_MPI @@ -208,53 +173,31 @@ class Connection } } - CoSimIO::ControlSignal RecvControlSignal(std::string& rIdentifier) - { - CO_SIM_IO_ERROR_IF(mIsConnectionMaster) << "This function can only be called as the Connection-Slave!" << std::endl; - return mpComm->RecvControlSignal(rIdentifier); - } - - void CheckIfFunctionNameIsValid(const std::string rFunctionName) const + void CheckIfNameIsValid(const std::string& rName) const { // could use set but that would require another include just for this - const static std::vector allowed_function_names { + const static std::vector allowed_names { "AdvanceInTime", "InitializeSolutionStep", "Predict", "SolveSolutionStep", "FinalizeSolutionStep", "OutputSolutionStep", - // "ImportGeometry", // not yet implemented - // "ExportGeometry", // not yet implemented "ImportMesh", "ExportMesh", "ImportData", - "ExportData" + "ExportData", + "exit" }; - CO_SIM_IO_ERROR_IF(std::find(allowed_function_names.begin(), allowed_function_names.end(), rFunctionName) == allowed_function_names.end()) << "The function name \"" << rFunctionName << "\" is not allowed!\nOnly the following names are allowed:\n"; // TODO print the names - } - - std::string ControlSignalName(const ControlSignal Signal) const - { - switch (Signal) { - // first two should not be needed here, this is intended to be used in "Run" - // case ControlSignal::Dummy: return "Dummy"; - // case ControlSignal::ConvergenceAchieved: return "ConvergenceAchieved"; - case ControlSignal::BreakSolutionLoop: return "BreakSolutionLoop"; - case ControlSignal::AdvanceInTime: return "AdvanceInTime"; - case ControlSignal::InitializeSolutionStep: return "InitializeSolutionStep"; - case ControlSignal::Predict: return "Predict"; - case ControlSignal::SolveSolutionStep: return "SolveSolutionStep"; - case ControlSignal::FinalizeSolutionStep: return "FinalizeSolutionStep"; - case ControlSignal::OutputSolutionStep: return "OutputSolutionStep"; - case ControlSignal::ImportGeometry: return "ImportGeometry"; - case ControlSignal::ExportGeometry: return "ExportGeometry"; - case ControlSignal::ImportMesh: return "ImportMesh"; - case ControlSignal::ExportMesh: return "ExportMesh"; - case ControlSignal::ImportData: return "ImportData"; - case ControlSignal::ExportData: return "ExportData"; - default: CO_SIM_IO_ERROR << "Signal is unknown: " << static_cast(Signal); return ""; + if (std::find(allowed_names.begin(), allowed_names.end(), rName) == allowed_names.end()) { + std::stringstream err_msg; + err_msg << "The name \"" << rName << "\" is not allowed!\nOnly the following names are allowed:"; + for (const auto& name : allowed_names) { + err_msg << "\n " << name; + } + err_msg << std::endl; + CO_SIM_IO_ERROR << err_msg.str(); } } @@ -263,4 +206,4 @@ class Connection } // namespace Internals } // namespace CoSimIO -#endif // CO_SIM_IO_CONNECTION_H_INCLUDED +#endif // CO_SIM_IO_CONNECTION_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/data_container.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/data_container.hpp index 909a3f7f0486..09218393b180 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/data_container.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/data_container.hpp @@ -10,15 +10,12 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_INTERNALS_H_INCLUDED -#define CO_SIM_IO_INTERNALS_H_INCLUDED +#ifndef CO_SIM_IO_DATA_CONTAINER_INCLUDED +#define CO_SIM_IO_DATA_CONTAINER_INCLUDED // System includes -#include -#include -#include #include -#include +#include // Project includes #include "define.hpp" @@ -31,8 +28,12 @@ template class DataContainer { public: + DataContainer() = default; virtual ~DataContainer() = default; + DataContainer(const DataContainer&) = delete; + DataContainer& operator=(const DataContainer&) = delete; + virtual std::size_t size() const = 0; virtual void resize(const std::size_t NewSize) = 0; @@ -55,7 +56,6 @@ class DataContainer } }; - /// output stream function template inline std::ostream& operator << (std::ostream& rOStream, @@ -98,7 +98,7 @@ class DataContainerStdVectorReadOnly : public DataContainer : mrVector(rVector) {} std::size_t size() const override {return mrVector.size();} - void resize(const std::size_t NewSize) override {CO_SIM_IO_ERROR << "Using non-const member of readonly object!" << std::endl;} + void resize(const std::size_t NewSize) override {CO_SIM_IO_ERROR << "Resizing of readonly object is not possible!" << std::endl;} const TDataType* data() const override {return mrVector.data();} TDataType* data() override {CO_SIM_IO_ERROR << "Using non-const member of readonly object!" << std::endl; return nullptr;} @@ -111,27 +111,31 @@ class DataContainerRawMemory : public DataContainer { public: explicit DataContainerRawMemory(TDataType** ppData, const std::size_t Size) - : mppData(ppData), mSize(Size) {} + : mppData(ppData), mSize(Size), mCapacity(Size) {} std::size_t size() const override {return mSize;}; void resize(const std::size_t NewSize) override { - if (NewSize > mSize) { // only increase the capacity if too small => same behavior as std::vector - if(mSize != 0) // Maybe is not null neigther allocated: double *data. Pooyan. - free(*mppData); // this is ok according to the standard, no matter if it is null or allocated //also check if using "std::" - - *mppData = (TDataType *)malloc((NewSize)*sizeof(TDataType)); // TODO maybe use realloc? //also check if using "std::" - CO_SIM_IO_ERROR_IF_NOT(*mppData) << "Memory reallocation failed"; - } mSize = NewSize; + if (NewSize > mCapacity) { // only increase the capacity if too small => same behavior as std::vector + if (mCapacity == 0) { + *mppData = nullptr; // initial allocation if not done outside + } + mCapacity = std::max(mCapacity*2, NewSize); // increase size beyond what is necessary to avoid frequent reallocations (like std::vector does) + + *mppData = (TDataType *)realloc(*mppData, (mCapacity)*sizeof(TDataType)); + CO_SIM_IO_ERROR_IF_NOT(*mppData) << "Memory reallocation failed!"; + } }; + const TDataType* data() const override {return *mppData;} TDataType* data() override {return *mppData;} private: TDataType** mppData; std::size_t mSize; + std::size_t mCapacity; }; template @@ -142,7 +146,7 @@ class DataContainerRawMemoryReadOnly : public DataContainer : mpData(pData), mSize(Size) {} std::size_t size() const override {return mSize;}; - void resize(const std::size_t NewSize) override {CO_SIM_IO_ERROR << "Using non-const member of readonly object!" << std::endl;}; + void resize(const std::size_t NewSize) override {CO_SIM_IO_ERROR << "Resizing of readonly object is not possible!" << std::endl;}; const TDataType* data() const override {return mpData;} TDataType* data() override {CO_SIM_IO_ERROR << "Using non-const member of readonly object!" << std::endl; return nullptr;} @@ -151,33 +155,7 @@ class DataContainerRawMemoryReadOnly : public DataContainer const std::size_t mSize; }; -inline void AddMissingSettings(const SettingsType& rDefaultSettings, SettingsType& rSettings) -{ - for (const auto& r_setting : rDefaultSettings) { - if (rSettings.count(r_setting.first) == 0) { - rSettings[r_setting.first] = r_setting.second; - } - } -} - -inline SettingsType ReadSettingsFile(const std::string& rSettingsFileName) -{ - std::ifstream settings_file(rSettingsFileName); - - if (!settings_file.good()) { - CO_SIM_IO_INFO("CoSimIO") << "Input file \"" << rSettingsFileName << "\" could not be read, using default configuration" << std::endl; - return SettingsType(); - } - - SettingsType settings; - std::string current_line; - while (std::getline(settings_file, current_line)) { - // TODO implement this - } - return settings; -} - } // namespace Internals } // namespace CoSimIO -#endif // CO_SIM_IO_INTERNALS_H_INCLUDED +#endif // CO_SIM_IO_DATA_CONTAINER_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/define.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/define.hpp index 3de8cc79512d..d9957541487a 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/define.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/define.hpp @@ -10,16 +10,22 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_DEFINE_H_INCLUDED -#define CO_SIM_IO_DEFINE_H_INCLUDED +#ifndef CO_SIM_IO_DEFINE_INCLUDED +#define CO_SIM_IO_DEFINE_INCLUDED // System includes -#include -#include +#include // std::ptrdiff_t +#include // std::unique_ptr +#include +#include namespace CoSimIO { -typedef std::unordered_map SettingsType; +// signed integer type, 32 bit in 32 bit systems, but 64bit in 64 bit systems => like std::size_t but signed +using IdType = std::ptrdiff_t; + +using CoordinatesType = std::array; +using ConnectivitiesType = std::vector; enum class ControlSignal { @@ -34,8 +40,6 @@ enum class ControlSignal FinalizeSolutionStep, OutputSolutionStep, - ImportGeometry, - ExportGeometry, ImportMesh, ExportMesh, ImportData, @@ -51,6 +55,39 @@ enum ConnectionStatus DisconnectionError }; +enum class ElementType +{ + Hexahedra3D20, + Hexahedra3D27, + Hexahedra3D8, + Prism3D15, + Prism3D6, + Quadrilateral2D4, + Quadrilateral2D8, + Quadrilateral2D9, + Quadrilateral3D4, + Quadrilateral3D8, + Quadrilateral3D9, + Tetrahedra3D10, + Tetrahedra3D4, + Triangle2D3, + Triangle2D6, + Triangle3D3, + Triangle3D6, + Line2D2, + Line2D3, + Line3D2, + Line3D3, + Point2D, + Point3D +}; + +// Note: std::make_unique is C++14, this can be updated once we upgrade from C++11 +template +std::unique_ptr make_unique(Args &&...args) { + return std::unique_ptr(new C(std::forward(args)...)); +} + } //namespace CoSimIO -#endif // CO_SIM_IO_DEFINE_H_INCLUDED \ No newline at end of file +#endif // CO_SIM_IO_DEFINE_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/filesystem_inc.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/filesystem_inc.hpp new file mode 100644 index 000000000000..58f1f4cd731a --- /dev/null +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/filesystem_inc.hpp @@ -0,0 +1,41 @@ +// ______ _____ _ ________ +// / ____/___ / ___/(_)___ ___ / _/ __ | +// / / / __ \\__ \/ / __ `__ \ / // / / / +// / /___/ /_/ /__/ / / / / / / // // /_/ / +// \____/\____/____/_/_/ /_/ /_/___/\____/ +// Kratos CoSimulationApplication +// +// License: BSD License, see license.txt +// +// Main authors: Philipp Bucher (https://github.com/philbucher) +// + +#ifndef CO_SIM_IO_FILESYSTEM_INC_INCLUDED +#define CO_SIM_IO_FILESYSTEM_INC_INCLUDED + +/* This file selects which implementation of std::filesystem to be used +std::filesystem is part of C++17 +When using only C++11 the alternative implementation from +"https://github.com/gulrak/filesystem" is used +*/ + +// To dynamically select std::filesystem where available, you could use: +#if defined(__cplusplus) && __cplusplus >= 201703L + #if __has_include() // has_include is C++17 + #define STD_FILESYSTEM_AVAILABLE + #include + namespace fs = std::filesystem; + #endif +#endif +#ifndef STD_FILESYSTEM_AVAILABLE + #define WIN32_LEAN_AND_MEAN + #define NOMINMAX + #include "../../external_libraries/ghc/filesystem.hpp" + #undef NOMINMAX + #undef WIN32_LEAN_AND_MEAN + namespace fs = ghc::filesystem; +#endif + +#undef STD_FILESYSTEM_AVAILABLE + +#endif // CO_SIM_IO_FILESYSTEM_INC_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/info.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/info.hpp index 2c6f0b252b21..156ecf925331 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/info.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/info.hpp @@ -112,9 +112,18 @@ class Info const TDataType& Get(const std::string& I_Key) const { CO_SIM_IO_ERROR_IF_NOT(Has(I_Key)) << "Trying to get \"" << I_Key << "\" which does not exist!" << std::endl; - const auto& r_val = mOptions.at(I_Key); - CO_SIM_IO_ERROR_IF(r_val->GetDataTypeName() != Internals::Name(TDataType())) << "Wrong DataType! Trying to get \"" << I_Key << "\" which is of type \"" << r_val->GetDataTypeName() << "\" with \"" << Internals::Name(TDataType()) << "\"!" << std::endl; - return *static_cast(r_val->GetData()); + return GetExistingKey(I_Key); + } + + template + const TDataType& Get(const std::string& I_Key, const TDataType& I_Default) const + { + if (Has(I_Key)) { + return GetExistingKey(I_Key); + } else { + // this does NOT insert the value! (same behavior as in python) + return I_Default; + } } bool Has(const std::string& I_Key) const @@ -213,6 +222,14 @@ class Info private: std::map> mOptions; + + template + const TDataType& GetExistingKey(const std::string& I_Key) const + { + const auto& r_val = mOptions.at(I_Key); + CO_SIM_IO_ERROR_IF(r_val->GetDataTypeName() != Internals::Name(TDataType())) << "Wrong DataType! Trying to get \"" << I_Key << "\" which is of type \"" << r_val->GetDataTypeName() << "\" with \"" << Internals::Name(TDataType()) << "\"!" << std::endl; + return *static_cast(r_val->GetData()); + } }; /// output stream function diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/macros.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/macros.hpp index a721d50ac743..63eaeec57059 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/macros.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/macros.hpp @@ -10,8 +10,8 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_MACROS_H_INCLUDED -#define CO_SIM_IO_MACROS_H_INCLUDED +#ifndef CO_SIM_IO_MACROS_INCLUDED +#define CO_SIM_IO_MACROS_INCLUDED /* This file defines macros that are used inside the CoSimIO Note that they are only defined here if they haven't been defined before. @@ -21,11 +21,59 @@ the code where the CoSimIO is included #ifndef CO_SIM_IO_ERROR #include + #include #include - struct err { // helper struct to mimic behavior of KRATOS_ERROR - ~err() noexcept(false) { throw std::runtime_error("Error: "); } // destructors are noexcept by default + #include + + namespace CoSimIO { + + // Simplified version of kratos/includes/exception.h + class Exception : public std::exception + { + public: + explicit Exception(const std::string& rWhat) : std::exception(), mMessage(rWhat) { } + + const char* what() const noexcept override + { + return mMessage.c_str(); + } + + /// string stream function + template + Exception& operator << (StreamValueType const& rValue) + { + std::stringstream buffer; + buffer << rValue; + + mMessage.append(buffer.str()); + + return *this; + } + + Exception& operator << (std::ostream& (*pf)(std::ostream&)) + { + std::stringstream buffer; + pf(buffer); + + mMessage.append(buffer.str()); + + return *this; + } + + Exception& operator << (const char* pString) + { + mMessage.append(pString); + return *this; + } + + private: + std::string mMessage; + }; - #define CO_SIM_IO_ERROR (err(), std::cout) + + } // namespace CoSimIO + + #define CO_SIM_IO_ERROR throw CoSimIO::Exception("Error: ") #endif #ifndef CO_SIM_IO_ERROR_IF @@ -33,7 +81,7 @@ the code where the CoSimIO is included #endif #ifndef CO_SIM_IO_ERROR_IF_NOT - #define CO_SIM_IO_ERROR_IF_NOT(conditional) if (!conditional) CO_SIM_IO_ERROR + #define CO_SIM_IO_ERROR_IF_NOT(conditional) if (!(conditional)) CO_SIM_IO_ERROR #endif #ifndef CO_SIM_IO_INFO @@ -45,4 +93,4 @@ the code where the CoSimIO is included #define CO_SIM_IO_INFO_IF(label, conditional) if (conditional) CO_SIM_IO_INFO(label) #endif -#endif // CO_SIM_IO_MACROS_H_INCLUDED \ No newline at end of file +#endif // CO_SIM_IO_MACROS_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/model_part.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/model_part.hpp new file mode 100644 index 000000000000..3663510ddabc --- /dev/null +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/model_part.hpp @@ -0,0 +1,321 @@ +// ______ _____ _ ________ +// / ____/___ / ___/(_)___ ___ / _/ __ | +// / / / __ \\__ \/ / __ `__ \ / // / / / +// / /___/ /_/ /__/ / / / / / / // // /_/ / +// \____/\____/____/_/_/ /_/ /_/___/\____/ +// Kratos CoSimulationApplication +// +// License: BSD License, see license.txt +// +// Main authors: Philipp Bucher (https://github.com/philbucher) +// + +#ifndef CO_SIM_IO_MODEL_PART_H_INCLUDED +#define CO_SIM_IO_MODEL_PART_H_INCLUDED + +/* This file contains the implementation of th CoSimIO::ModelPart +It serves as a data container when exchanging data +Also it is used in order to be consistent with Kratos to reduce compatibility problems +This is a simplified version of Kratos::ModelPart +see https://github.com/KratosMultiphysics/Kratos/blob/master/kratos/includes/model_part.h +*/ + +// System includes +#include +#include +#include +#include +#include + +// Project includes +#include "define.hpp" +#include "macros.hpp" +#include "utilities.hpp" + +namespace CoSimIO { + +class Node +{ +public: + Node( + const IdType I_Id, + const double I_X, + const double I_Y, + const double I_Z) + : mId(I_Id), + mX(I_X), + mY(I_Y), + mZ(I_Z) + { + CO_SIM_IO_ERROR_IF(I_Id < 1) << "Id must be >= 1!" << std::endl; + } + + Node( + const IdType I_Id, + const CoordinatesType& I_Coordinates) + : Node(I_Id, I_Coordinates[0], I_Coordinates[1], I_Coordinates[2]) + { } + + // delete copy and assignment CTor + Node(const Node&) = delete; + Node& operator=(Node const&) = delete; + + IdType Id() const { return mId; } + double X() const { return mX; } + double Y() const { return mY; } + double Z() const { return mZ; } + CoordinatesType Coordinates() const { return {mX, mY, mZ}; } + + void Print(std::ostream& rOStream) const + { + rOStream << "CoSimIO-Node; Id: " << Id() << "\n"; + rOStream << " Coordinates: [ " << X() << " | " << Y() << " | " << Z() << " ]" << std::endl; + } + +private: + IdType mId; + double mX; + double mY; + double mZ; +}; + +/// output stream function +inline std::ostream & operator <<( + std::ostream& rOStream, + const Node& rThis) +{ + rThis.Print(rOStream); + return rOStream; +} + + +class Element +{ +public: + using NodesContainerType = std::vector; + + Element( + const IdType I_Id, + const ElementType I_Type, + const NodesContainerType& I_Nodes) + : mId(I_Id), + mType(I_Type), + mNodes(I_Nodes) + { + CO_SIM_IO_ERROR_IF(I_Id < 1) << "Id must be >= 1!" << std::endl; + CO_SIM_IO_ERROR_IF(NumberOfNodes() < 1) << "No nodes were passed!" << std::endl; + const int num_nodes_elem_type = CoSimIO::Internals::GetNumberOfNodesForElementType(I_Type); + CO_SIM_IO_ERROR_IF_NOT(num_nodes_elem_type == static_cast(NumberOfNodes())) << "Number of nodes (" << NumberOfNodes() << ") does not match expected number for element type (" << num_nodes_elem_type << ")!" << std::endl; + } + + // delete copy and assignment CTor + Element(const Element&) = delete; + Element& operator=(Element const&) = delete; + + IdType Id() const { return mId; } + ElementType Type() const { return mType; } + std::size_t NumberOfNodes() const { return mNodes.size(); } + NodesContainerType::const_iterator NodesBegin() const { return mNodes.begin(); } + NodesContainerType::const_iterator NodesEnd() const { return mNodes.end(); } + + void Print(std::ostream& rOStream) const + { + rOStream << "CoSimIO-Element; Id: " << Id() << "\n"; + rOStream << " Number of Nodes: " << NumberOfNodes() << "\n"; + rOStream << " Node Ids: "; + if (NumberOfNodes() > 0) { + rOStream << mNodes[0]->Id(); + } + for (std::size_t i=1; iId(); + } + rOStream << std::endl; + } + +private: + IdType mId; + ElementType mType; + NodesContainerType mNodes; +}; + +/// output stream function +inline std::ostream & operator <<( + std::ostream& rOStream, + const Element& rThis) +{ + rThis.Print(rOStream); + return rOStream; +} + + +class ModelPart +{ +public: + + using NodePointerType = std::shared_ptr; // TODO switch to intrusive_ptr + using ElementPointerType = std::shared_ptr; // TODO switch to intrusive_ptr + using NodesContainerType = std::vector; + using ElementsContainerType = std::vector; + + explicit ModelPart(const std::string& I_Name) : mName(I_Name) + { + CO_SIM_IO_ERROR_IF(I_Name.empty()) << "Please don't use empty names (\"\") when creating a ModelPart" << std::endl; + CO_SIM_IO_ERROR_IF_NOT(I_Name.find(".") == std::string::npos) << "Please don't use names containing (\".\") when creating a ModelPart (used in \"" << I_Name << "\")" << std::endl; + } + + // delete copy and assignment CTor + ModelPart(const ModelPart&) = delete; + ModelPart& operator=(ModelPart const&) = delete; + + const std::string& Name() const { return mName; } + std::size_t NumberOfNodes() const { return mNodes.size(); } + std::size_t NumberOfElements() const { return mElements.size(); } + + Node& CreateNewNode( + const IdType I_Id, + const double I_X, + const double I_Y, + const double I_Z) + { + CO_SIM_IO_ERROR_IF(HasNode(I_Id)) << "The Node with Id " << I_Id << " exists already!" << std::endl; + + mNodes.push_back(std::make_shared(I_Id, I_X, I_Y, I_Z)); + return *(mNodes.back()); + } + + Element& CreateNewElement( + const IdType I_Id, + const ElementType I_Type, + const ConnectivitiesType& I_Connectivities) + { + CO_SIM_IO_ERROR_IF(HasElement(I_Id)) << "The Element with Id " << I_Id << " exists already!" << std::endl; + + Element::NodesContainerType nodes; + nodes.reserve(I_Connectivities.size()); + for (const IdType node_id : I_Connectivities) { + nodes.push_back(&GetNode(node_id)); + } + mElements.push_back(std::make_shared(I_Id, I_Type, nodes)); + return *(mElements.back()); + } + + NodesContainerType::const_iterator NodesBegin() const { return mNodes.begin(); } + ElementsContainerType::const_iterator ElementsBegin() const { return mElements.begin(); } + + NodesContainerType::const_iterator NodesEnd() const { return mNodes.end(); } + ElementsContainerType::const_iterator ElementsEnd() const { return mElements.end(); } + + Node& GetNode(const IdType I_Id) + { + auto it_node = FindNode(I_Id); + CO_SIM_IO_ERROR_IF(it_node == mNodes.end()) << "Node with Id " << I_Id << " does not exist!" << std::endl; + return **it_node; + } + + const Node& GetNode(const IdType I_Id) const + { + auto it_node = FindNode(I_Id); + CO_SIM_IO_ERROR_IF(it_node == mNodes.end()) << "Node with Id " << I_Id << " does not exist!" << std::endl; + return **it_node; + } + + NodePointerType pGetNode(const IdType I_Id) + { + auto it_node = FindNode(I_Id); + CO_SIM_IO_ERROR_IF(it_node == mNodes.end()) << "Node with Id " << I_Id << " does not exist!" << std::endl; + return *it_node; + } + + Element& GetElement(const IdType I_Id) + { + auto it_elem = FindElement(I_Id); + CO_SIM_IO_ERROR_IF(it_elem == mElements.end()) << "Element with Id " << I_Id << " does not exist!" << std::endl; + return **it_elem; + } + + const Element& GetElement(const IdType I_Id) const + { + auto it_elem = FindElement(I_Id); + CO_SIM_IO_ERROR_IF(it_elem == mElements.end()) << "Element with Id " << I_Id << " does not exist!" << std::endl; + return **it_elem; + } + + ElementPointerType pGetElement(const IdType I_Id) + { + auto it_elem = FindElement(I_Id); + CO_SIM_IO_ERROR_IF(it_elem == mElements.end()) << "Element with Id " << I_Id << " does not exist!" << std::endl; + return *it_elem; + } + + void Print(std::ostream& rOStream) const + { + rOStream << "CoSimIO-ModelPart \"" << mName << "\"\n"; + rOStream << " Number of Nodes: " << NumberOfNodes() << "\n"; + rOStream << " Number of Elements: " << NumberOfElements() << std::endl; + } + + void Clear() + { + mElements.clear(); + mElements.shrink_to_fit(); + + mNodes.clear(); + mNodes.shrink_to_fit(); + } + +private: + std::string mName; + NodesContainerType mNodes; + ElementsContainerType mElements; + + NodesContainerType::const_iterator FindNode(const IdType I_Id) const + { + return std::find_if( + mNodes.begin(), mNodes.end(), + [I_Id](const NodePointerType& rp_node) { return rp_node->Id() == I_Id;}); + } + + NodesContainerType::iterator FindNode(const IdType I_Id) + { + return std::find_if( + mNodes.begin(), mNodes.end(), + [I_Id](const NodePointerType& rp_node) { return rp_node->Id() == I_Id;}); + } + + ElementsContainerType::const_iterator FindElement(const IdType I_Id) const + { + return std::find_if( + mElements.begin(), mElements.end(), + [I_Id](const ElementPointerType& rp_elem) { return rp_elem->Id() == I_Id;}); + } + + ElementsContainerType::iterator FindElement(const IdType I_Id) + { + return std::find_if( + mElements.begin(), mElements.end(), + [I_Id](const ElementPointerType& rp_elem) { return rp_elem->Id() == I_Id;}); + } + + bool HasNode(const IdType I_Id) const + { + return FindNode(I_Id) != mNodes.end(); + } + + bool HasElement(const IdType I_Id) const + { + return FindElement(I_Id) != mElements.end(); + } +}; + +/// output stream function +inline std::ostream & operator <<( + std::ostream& rOStream, + const ModelPart& rThis) +{ + rThis.Print(rOStream); + return rOStream; +} + +} //namespace CoSimIO + +#endif // CO_SIM_IO_MODEL_PART_H_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/utilities.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/utilities.hpp new file mode 100644 index 000000000000..42f1868dbb07 --- /dev/null +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/utilities.hpp @@ -0,0 +1,99 @@ +// ______ _____ _ ________ +// / ____/___ / ___/(_)___ ___ / _/ __ | +// / / / __ \\__ \/ / __ `__ \ / // / / / +// / /___/ /_/ /__/ / / / / / / // // /_/ / +// \____/\____/____/_/_/ /_/ /_/___/\____/ +// Kratos CoSimulationApplication +// +// License: BSD License, see license.txt +// +// Main authors: Philipp Bucher (https://github.com/philbucher) +// + +#ifndef CO_SIM_IO_UTILITIES_INCLUDED +#define CO_SIM_IO_UTILITIES_INCLUDED + +// System includes +#include +#include +#include + +// Project includes +#include "define.hpp" +#include "macros.hpp" + +namespace CoSimIO { +namespace Internals { + +// Create the name for the connection +// In a function bcs maybe in the future this will +// need to be more elaborate +inline std::string CreateConnectionName( + const std::string& rName1, + const std::string& rName2) +{ + if (rName1 < rName2) { + return rName1 + "_" + rName2; + } else { + return rName2 + "_" + rName1; + } +} + +inline void CheckEntry(const std::string& rEntry, const std::string& rKey) +{ + // the entries are used e.g. for the folder creation, file names and other things + // hence they are a little bit restricted to avoid unfortunate failures in rare cases + + const std::size_t max_allowed_size = 1000; + CO_SIM_IO_ERROR_IF(rEntry.empty()) << "Using an empty entry for \"" << rKey << "\" is not allowed!" << std::endl; + CO_SIM_IO_ERROR_IF(rEntry.length() > max_allowed_size) << "Entry for \"" << rKey << "\" is too long! Maximum allowed length: " << max_allowed_size << " characters!" << std::endl; + + const char disallowed_chars[] = {'.', ',', ':', ';', '>', '<', '/', '\'', '|', '*', '!', '"', ' '}; + for (const auto ch : disallowed_chars) { + CO_SIM_IO_ERROR_IF_NOT(rEntry.find(ch) == std::string::npos) << "Entry for \"" << rKey << "\" contains a character that is not allowed: \"" << std::string(1,ch) << "\"!" << std::endl; + } +} + +inline double ElapsedSeconds(const std::chrono::steady_clock::time_point& rStartTime) +{ + using namespace std::chrono; + return duration_cast>(steady_clock::now() - rStartTime).count(); +} + +inline int GetNumberOfNodesForElementType(ElementType Type) +{ + const std::map type_num_nodes_map { + {ElementType::Hexahedra3D20, 20}, + {ElementType::Hexahedra3D27, 27}, + {ElementType::Hexahedra3D8, 8}, + {ElementType::Prism3D15, 15}, + {ElementType::Prism3D6, 6}, + {ElementType::Quadrilateral2D4, 4}, + {ElementType::Quadrilateral2D8, 8}, + {ElementType::Quadrilateral2D9, 9}, + {ElementType::Quadrilateral3D4, 4}, + {ElementType::Quadrilateral3D8, 8}, + {ElementType::Quadrilateral3D9, 9}, + {ElementType::Tetrahedra3D10, 10}, + {ElementType::Tetrahedra3D4, 4}, + {ElementType::Triangle2D3, 3}, + {ElementType::Triangle2D6, 6}, + {ElementType::Triangle3D3, 3}, + {ElementType::Triangle3D6, 6}, + {ElementType::Line2D2, 2}, + {ElementType::Line2D3, 3}, + {ElementType::Line3D2, 2}, + {ElementType::Line3D3, 3}, + {ElementType::Point2D, 1}, + {ElementType::Point3D, 1} + }; + + auto type_iter = type_num_nodes_map.find(Type); + CO_SIM_IO_ERROR_IF(type_iter == type_num_nodes_map.end()) << "Unsupported element type: " << static_cast(Type) << std::endl; + return type_iter->second; +} + +} // namespace Internals +} // namespace CoSimIO + +#endif // CO_SIM_IO_UTILITIES_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/version.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/version.hpp index 615c7981eb74..65719e87ec65 100644 --- a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/version.hpp +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/version.hpp @@ -10,8 +10,8 @@ // Main authors: Philipp Bucher (https://github.com/philbucher) // -#ifndef CO_SIM_IO_VERSION_H_INCLUDED -#define CO_SIM_IO_VERSION_H_INCLUDED +#ifndef CO_SIM_IO_VERSION_INCLUDED +#define CO_SIM_IO_VERSION_INCLUDED // System includes #include @@ -19,17 +19,17 @@ namespace CoSimIO { constexpr int GetMajorVersion() { - return 1; + return 2; } constexpr int GetMinorVersion() { return 0; } -std::string GetPatchVersion() { +inline std::string GetPatchVersion() { return "0"; } } // namespace CoSimIO -#endif // CO_SIM_IO_VERSION_H_INCLUDED +#endif // CO_SIM_IO_VERSION_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/vtk_utilities.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/vtk_utilities.hpp new file mode 100644 index 000000000000..c59945328d35 --- /dev/null +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/impl/vtk_utilities.hpp @@ -0,0 +1,76 @@ +// ______ _____ _ ________ +// / ____/___ / ___/(_)___ ___ / _/ __ | +// / / / __ \\__ \/ / __ `__ \ / // / / / +// / /___/ /_/ /__/ / / / / / / // // /_/ / +// \____/\____/____/_/_/ /_/ /_/___/\____/ +// Kratos CoSimulationApplication +// +// License: BSD License, see license.txt +// +// Main authors: Philipp Bucher (https://github.com/philbucher) +// + +#ifndef CO_SIM_IO_VTK_UTILITIES_INCLUDED +#define CO_SIM_IO_VTK_UTILITIES_INCLUDED + +// System includes +#include + +// Project includes +#include "define.hpp" +#include "macros.hpp" + +namespace CoSimIO { +namespace Internals { + +// see https://vtk.org/wp-content/uploads/2015/04/file-formats.pdf ; figure 2 +enum class VtkCellType { + Vertex = 1, + Line = 3, + Triangle = 5, + Quad = 9, + Tetra = 10, + Hexahedron = 12, + Wedge = 13, + Pyramid = 14, + + Quadratic_Edge = 21, + Quadratic_Triangle = 22, + Quadratic_Quad = 23, + Quadratic_Tetra = 24, + Quadratic_Hexahedron = 25, +}; + +inline VtkCellType GetVtkCellTypeForElementType(ElementType I_ElementType) +{ + const std::map element_type_to_cell_Type_map = { + {ElementType::Hexahedra3D20, VtkCellType::Quadratic_Hexahedron}, + {ElementType::Hexahedra3D8, VtkCellType::Hexahedron}, + {ElementType::Prism3D6, VtkCellType::Wedge}, + {ElementType::Quadrilateral2D4, VtkCellType::Quad}, + {ElementType::Quadrilateral2D8, VtkCellType::Quadratic_Quad}, + {ElementType::Quadrilateral3D4, VtkCellType::Quad}, + {ElementType::Quadrilateral3D8, VtkCellType::Quadratic_Quad}, + {ElementType::Tetrahedra3D10, VtkCellType::Quadratic_Tetra}, + {ElementType::Tetrahedra3D4, VtkCellType::Tetra}, + {ElementType::Triangle2D3, VtkCellType::Triangle}, + {ElementType::Triangle2D6, VtkCellType::Quadratic_Triangle}, + {ElementType::Triangle3D3, VtkCellType::Triangle}, + {ElementType::Triangle3D6, VtkCellType::Quadratic_Triangle}, + {ElementType::Line2D2, VtkCellType::Line}, + {ElementType::Line2D3, VtkCellType::Quadratic_Edge}, + {ElementType::Line3D2, VtkCellType::Line}, + {ElementType::Line3D3, VtkCellType::Quadratic_Edge}, + {ElementType::Point2D, VtkCellType::Vertex}, + {ElementType::Point3D, VtkCellType::Vertex} + }; + + auto type_iter = element_type_to_cell_Type_map.find(I_ElementType); + CO_SIM_IO_ERROR_IF(type_iter == element_type_to_cell_Type_map.end()) << "Unsupported element type: " << static_cast(I_ElementType) << std::endl; // TODO maybe return -1 or so here in the future. This way also types not supported by vtk/Paraview could be used with CoSomIO (but not visualized in Paraview) + return type_iter->second; +} + +} // namespace Internals +} // namespace CoSimIO + +#endif // CO_SIM_IO_VTK_UTILITIES_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/connection_status_to_python.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/connection_status_to_python.hpp new file mode 100644 index 000000000000..2f6a9d7ab185 --- /dev/null +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/connection_status_to_python.hpp @@ -0,0 +1,43 @@ +// ______ _____ _ ________ +// / ____/___ / ___/(_)___ ___ / _/ __ | +// / / / __ \\__ \/ / __ `__ \ / // / / / +// / /___/ /_/ /__/ / / / / / / // // /_/ / +// \____/\____/____/_/_/ /_/ /_/___/\____/ +// Kratos CoSimulationApplication +// +// License: BSD License, see license.txt +// +// Main authors: Philipp Bucher (https://github.com/philbucher) +// + +#ifndef CO_SIM_IO_CONNECTION_STATUS_TO_PYHON_INCLUDED +#define CO_SIM_IO_CONNECTION_STATUS_TO_PYHON_INCLUDED + +// Exposure of the CoSimIO to Python + +// System includes + +// pybind includes +#include + +// CoSimIO include +#include "../co_sim_io.hpp" + +namespace CoSimIO { + +void AddCoSimIOConnectionStatusToPython(pybind11::module& m) +{ + namespace py = pybind11; + + py::enum_(m,"ConnectionStatus") + .value("NotConnected",CoSimIO::ConnectionStatus::NotConnected) + .value("Connected",CoSimIO::ConnectionStatus::Connected) + .value("Disconnected", CoSimIO::ConnectionStatus::Disconnected) + .value("ConnectionError", CoSimIO::ConnectionStatus::ConnectionError) + .value("DisconnectionError", CoSimIO::ConnectionStatus::DisconnectionError) + ; +} + +} // namespace CoSimIO + +#endif // CO_SIM_IO_CONNECTION_STATUS_TO_PYHON_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/info_to_python.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/info_to_python.hpp new file mode 100644 index 000000000000..a2000b5239f4 --- /dev/null +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/info_to_python.hpp @@ -0,0 +1,66 @@ +// ______ _____ _ ________ +// / ____/___ / ___/(_)___ ___ / _/ __ | +// / / / __ \\__ \/ / __ `__ \ / // / / / +// / /___/ /_/ /__/ / / / / / / // // /_/ / +// \____/\____/____/_/_/ /_/ /_/___/\____/ +// Kratos CoSimulationApplication +// +// License: BSD License, see license.txt +// +// Main authors: Philipp Bucher (https://github.com/philbucher) +// + +#ifndef CO_SIM_IO_INFO_TO_PYHON_INCLUDED +#define CO_SIM_IO_INFO_TO_PYHON_INCLUDED + +// Exposure of the CoSimIO to Python + +// System includes +#include +#include + +// pybind includes +#include + +// CoSimIO include +#include "../co_sim_io.hpp" + +namespace { + +template +void AddGetSetInterface(pybind11::class_& PythonInfo, const std::string& Name) +{ + PythonInfo.def(std::string("Get"+Name).c_str(), [](const CoSimIO::Info& I_Info, const std::string& I_Key){return I_Info.Get(I_Key);}); + PythonInfo.def(std::string("Get"+Name).c_str(), [](const CoSimIO::Info& I_Info, const std::string& I_Key, const TDataType& I_Default){return I_Info.Get(I_Key, I_Default);}); + PythonInfo.def(std::string("Set"+Name).c_str(), &CoSimIO::Info::Set); +} + +} + +namespace CoSimIO { + +void AddCoSimIOInfoToPython(pybind11::module& m) +{ + namespace py = pybind11; + + auto py_info = py::class_(m,"Info") + .def(py::init<>()) + .def(py::init()) + .def("Has", &CoSimIO::Info::Has) + .def("Erase", &CoSimIO::Info::Erase) + .def("Clear", &CoSimIO::Info::Clear) + .def("Size", &CoSimIO::Info::Size) + .def("__len__", [](const CoSimIO::Info& I_Info){return I_Info.Size();}) + .def("__str__", [](const CoSimIO::Info& I_Info) + { std::stringstream ss; ss << I_Info; return ss.str(); } ) + ; + + AddGetSetInterface(py_info, "Int"); + AddGetSetInterface(py_info, "Double"); + AddGetSetInterface(py_info, "Bool"); + AddGetSetInterface(py_info, "String"); +} + +} // namespace CoSimIO + +#endif // CO_SIM_IO_INFO_TO_PYHON_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/vector_to_python.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/vector_to_python.hpp new file mode 100644 index 000000000000..7ae352dbe69b --- /dev/null +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/vector_to_python.hpp @@ -0,0 +1,131 @@ +// ______ _____ _ ________ +// / ____/___ / ___/(_)___ ___ / _/ __ | +// / / / __ \\__ \/ / __ `__ \ / // / / / +// / /___/ /_/ /__/ / / / / / / // // /_/ / +// \____/\____/____/_/_/ /_/ /_/___/\____/ +// Kratos CoSimulationApplication +// +// License: BSD License, see license.txt +// +// Main authors: Philipp Bucher (https://github.com/philbucher) +// + +#ifndef CO_SIM_IO_VECTOR_TO_PYHON_INCLUDED +#define CO_SIM_IO_VECTOR_TO_PYHON_INCLUDED + +// Exposure of the CoSimIO to Python + +// System includes +#include +#include + +// pybind includes +#include +#include + +// +#include "../impl/define.hpp" + +namespace CoSimIO { + +// small wrapper around std::vector for using it in Python +// Note: deliberately not using PYBIND11_MAKE_OPAQUE as this +// can be problematic if integrated in other libraries +template +class VectorWrapper +{ +public: + VectorWrapper() = default; + explicit VectorWrapper(const std::size_t I_Size) { mVector.resize(I_Size); } + explicit VectorWrapper(const std::vector& I_Vector) + : mVector(I_Vector) {}; + + VectorWrapper(const VectorWrapper& Other) : mVector(Other.mVector) {} + VectorWrapper& operator=(const VectorWrapper&) = delete; + + std::vector& Vector() {return mVector;} + const std::vector& Vector() const {return mVector;} + +private: + std::vector mVector; +}; + +} // namespace CoSimIO + +namespace { // anonymous namespace + +template +void AddVectorWithTypeToPython(pybind11::module& m, const std::string& Name) +{ + namespace py = pybind11; + + using VectorType = CoSimIO::VectorWrapper; + + const std::string full_name = Name+"Vector"; + + py::class_(m, full_name.c_str()) + .def(py::init<>()) + .def(py::init()) + .def(py::init( [](const py::list& l){ + VectorType vec(l.size()); + for(std::size_t i=0; i(l[i]); + } + return vec; + })) + .def(py::init( [Name](py::buffer b){ + py::buffer_info info = b.request(); + CO_SIM_IO_ERROR_IF(info.format != py::format_descriptor::value) << "Expected a " << Name << " array!"; + CO_SIM_IO_ERROR_IF(info.ndim != 1) << "Buffer dimension of 1 is required, got: " << info.ndim << std::endl; + VectorType vec(info.shape[0]); + for (int i=0; i(info.ptr)[i]; + } + return vec; + })) + + .def("__len__", [](VectorType& v) + { return v.Vector().size(); } ) + .def("size", [](VectorType& v) + { return v.Vector().size(); } ) + .def("resize", [](VectorType& v, const std::size_t& size) + { v.Vector().resize(size); } ) + .def("append", [](VectorType& v, const TDataType& val) + { v.Vector().push_back(val); } ) + .def("__setitem__", [](VectorType& v, const std::size_t I_Index, const TDataType& val) + { v.Vector()[I_Index] = val; } ) + .def("__getitem__", [](VectorType& v, const std::size_t I_Index) + { return v.Vector()[I_Index]; } ) + .def("__iter__", [](VectorType& v) + {return py::make_iterator(v.Vector().begin(), v.Vector().end());}, py::keep_alive<0,1>()) + + .def("__str__", [](const VectorType& v) + { + std::stringstream ss; + const std::size_t size = v.Vector().size(); + + ss << "["; + if(size>0) ss << v.Vector()[0]; + if(size>1) { + for(std::size_t i=1; i(m, "Int"); + AddVectorWithTypeToPython(m, "Double"); +} + +} // namespace CoSimIO + +#endif // CO_SIM_IO_VECTOR_TO_PYHON_INCLUDED diff --git a/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/version_to_python.hpp b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/version_to_python.hpp new file mode 100644 index 000000000000..f61e5344c47e --- /dev/null +++ b/applications/CoSimulationApplication/custom_external_libraries/co_sim_io/python/version_to_python.hpp @@ -0,0 +1,43 @@ +// ______ _____ _ ________ +// / ____/___ / ___/(_)___ ___ / _/ __ | +// / / / __ \\__ \/ / __ `__ \ / // / / / +// / /___/ /_/ /__/ / / / / / / // // /_/ / +// \____/\____/____/_/_/ /_/ /_/___/\____/ +// Kratos CoSimulationApplication +// +// License: BSD License, see license.txt +// +// Main authors: Philipp Bucher (https://github.com/philbucher) +// + +#ifndef CO_SIM_IO_VERSION_TO_PYHON_INCLUDED +#define CO_SIM_IO_VERSION_TO_PYHON_INCLUDED + +// Exposure of the CoSimIO to Python + +// System includes +#include +#include + +// pybind includes +#include + +// CoSimIO include +#include "../co_sim_io.hpp" + +namespace CoSimIO { + +void AddCoSimIOVersionToPython(pybind11::module& m) +{ + namespace py = pybind11; + + std::stringstream version_stream; + version_stream << CoSimIO::GetMajorVersion() << "." + << CoSimIO::GetMinorVersion() << "." + << CoSimIO::GetPatchVersion(); + m.attr("__version__") = version_stream.str(); +} + +} // namespace CoSimIO + +#endif // CO_SIM_IO_VERSION_TO_PYHON_INCLUDED diff --git a/applications/CoSimulationApplication/custom_python/add_co_sim_io_to_python.cpp b/applications/CoSimulationApplication/custom_python/add_co_sim_io_to_python.cpp index 82ca1c846e1b..9e3459eac607 100644 --- a/applications/CoSimulationApplication/custom_python/add_co_sim_io_to_python.cpp +++ b/applications/CoSimulationApplication/custom_python/add_co_sim_io_to_python.cpp @@ -32,6 +32,11 @@ #define CO_SIM_IO_ERROR_IF_NOT KRATOS_ERROR_IF_NOT #include "custom_external_libraries/co_sim_io/co_sim_io.hpp" +#include "custom_external_libraries/co_sim_io/python/connection_status_to_python.hpp" +#include "custom_external_libraries/co_sim_io/python/info_to_python.hpp" +#include "custom_external_libraries/co_sim_io/python/vector_to_python.hpp" +#include "custom_external_libraries/co_sim_io/python/version_to_python.hpp" + namespace Kratos { namespace Python { @@ -44,122 +49,142 @@ namespace CoSimIO_Wrappers { // helpers namespace // defining the static members struct DataBuffers { static std::vector vector_doubles; - static std::vector vector_connectivities; - static std::vector vector_types; }; // declaring the static members std::vector DataBuffers::vector_doubles; -std::vector DataBuffers::vector_connectivities; -std::vector DataBuffers::vector_types; +const std::map elem_type_map { + {GeometryData::KratosGeometryType::Kratos_Hexahedra3D20, CoSimIO::ElementType::Hexahedra3D20 }, + {GeometryData::KratosGeometryType::Kratos_Hexahedra3D27, CoSimIO::ElementType::Hexahedra3D27 }, + {GeometryData::KratosGeometryType::Kratos_Hexahedra3D8, CoSimIO::ElementType::Hexahedra3D8 }, + {GeometryData::KratosGeometryType::Kratos_Prism3D15, CoSimIO::ElementType::Prism3D15 }, + {GeometryData::KratosGeometryType::Kratos_Prism3D6, CoSimIO::ElementType::Prism3D6 }, + {GeometryData::KratosGeometryType::Kratos_Quadrilateral2D4, CoSimIO::ElementType::Quadrilateral2D4 }, + {GeometryData::KratosGeometryType::Kratos_Quadrilateral2D8, CoSimIO::ElementType::Quadrilateral2D8 }, + {GeometryData::KratosGeometryType::Kratos_Quadrilateral2D9, CoSimIO::ElementType::Quadrilateral2D9 }, + {GeometryData::KratosGeometryType::Kratos_Quadrilateral3D4, CoSimIO::ElementType::Quadrilateral3D4 }, + {GeometryData::KratosGeometryType::Kratos_Quadrilateral3D8, CoSimIO::ElementType::Quadrilateral3D8 }, + {GeometryData::KratosGeometryType::Kratos_Quadrilateral3D9, CoSimIO::ElementType::Quadrilateral3D9 }, + {GeometryData::KratosGeometryType::Kratos_Tetrahedra3D10, CoSimIO::ElementType::Tetrahedra3D10 }, + {GeometryData::KratosGeometryType::Kratos_Tetrahedra3D4, CoSimIO::ElementType::Tetrahedra3D4 }, + {GeometryData::KratosGeometryType::Kratos_Triangle2D3, CoSimIO::ElementType::Triangle2D3 }, + {GeometryData::KratosGeometryType::Kratos_Triangle2D6, CoSimIO::ElementType::Triangle2D6 }, + {GeometryData::KratosGeometryType::Kratos_Triangle3D3, CoSimIO::ElementType::Triangle3D3 }, + {GeometryData::KratosGeometryType::Kratos_Triangle3D6, CoSimIO::ElementType::Triangle3D6 }, + {GeometryData::KratosGeometryType::Kratos_Line2D2, CoSimIO::ElementType::Line2D2 }, + {GeometryData::KratosGeometryType::Kratos_Line2D3, CoSimIO::ElementType::Line2D3 }, + {GeometryData::KratosGeometryType::Kratos_Line3D2, CoSimIO::ElementType::Line3D2 }, + {GeometryData::KratosGeometryType::Kratos_Line3D3, CoSimIO::ElementType::Line3D3 }, + {GeometryData::KratosGeometryType::Kratos_Point2D, CoSimIO::ElementType::Point2D }, + {GeometryData::KratosGeometryType::Kratos_Point3D, CoSimIO::ElementType::Point3D } +}; + +const std::map elem_name_map { + {CoSimIO::ElementType::Hexahedra3D20, "Element3D20N"}, + {CoSimIO::ElementType::Hexahedra3D27, "Element3D27N"}, + {CoSimIO::ElementType::Hexahedra3D8, "Element3D8N"}, + {CoSimIO::ElementType::Prism3D15, "Element3D15N"}, + {CoSimIO::ElementType::Prism3D6, "Element3D6N"}, + {CoSimIO::ElementType::Quadrilateral2D4, "Element2D4N"}, + {CoSimIO::ElementType::Quadrilateral2D8, "Element2D8N"}, + {CoSimIO::ElementType::Quadrilateral2D9, "Element2D9N"}, + {CoSimIO::ElementType::Quadrilateral3D8, "Element3D8N"}, + {CoSimIO::ElementType::Tetrahedra3D10, "Element3D10N"}, + {CoSimIO::ElementType::Tetrahedra3D4, "Element3D4N"}, + {CoSimIO::ElementType::Triangle2D3, "Element2D3N"}, + {CoSimIO::ElementType::Triangle2D6, "Element2D6N"}, + {CoSimIO::ElementType::Triangle3D3, "Element3D3N"}, + {CoSimIO::ElementType::Line2D2, "Element2D2N"}, + {CoSimIO::ElementType::Line3D2, "Element3D2N"}, + {CoSimIO::ElementType::Point2D, "Element2D1N"}, + {CoSimIO::ElementType::Point3D, "Element3D1N"} +}; void ExportMesh( CoSimIO::Info& rInfo, const ModelPart& rModelPart) { - // extract information from ModelPart - const int num_nodes = rModelPart.NumberOfNodes(); - const int num_elems = rModelPart.NumberOfElements(); + CoSimIO::ModelPart co_sim_io_model_part(rModelPart.Name()); - DataBuffers::vector_doubles.resize(num_nodes*3); - DataBuffers::vector_types.resize(num_elems); - DataBuffers::vector_connectivities.clear(); - - std::size_t node_counter = 0; for (const auto& r_node : rModelPart.Nodes()) { - const auto& r_coords = r_node.GetInitialPosition(); // TODO or current coords? - DataBuffers::vector_doubles[node_counter++] = r_coords[0]; - DataBuffers::vector_doubles[node_counter++] = r_coords[1]; - DataBuffers::vector_doubles[node_counter++] = r_coords[2]; - } - - // NOTE: See https://vtk.org/wp-content/uploads/2015/04/file-formats.pdf - const std::map geo_type_vtk_cell_type_map = { - { GeometryData::KratosGeometryType::Kratos_Point2D, 1 }, - { GeometryData::KratosGeometryType::Kratos_Point3D, 1 }, - { GeometryData::KratosGeometryType::Kratos_Line2D2, 3 }, - { GeometryData::KratosGeometryType::Kratos_Line3D2, 3 }, - { GeometryData::KratosGeometryType::Kratos_Triangle2D3, 5 }, - { GeometryData::KratosGeometryType::Kratos_Triangle3D3, 5 }, - { GeometryData::KratosGeometryType::Kratos_Quadrilateral2D4, 9 }, - { GeometryData::KratosGeometryType::Kratos_Quadrilateral3D4, 9 }, - { GeometryData::KratosGeometryType::Kratos_Tetrahedra3D4, 10 }, - { GeometryData::KratosGeometryType::Kratos_Hexahedra3D8, 12 } + co_sim_io_model_part.CreateNewNode( + r_node.Id(), + // TODO: use initial or current coordinates? + r_node.X0(), + r_node.Y0(), + r_node.Z0() + ); }; - std::size_t elem_counter = 0; - int connectivities_offset = std::numeric_limits::max(); //in paraview the connectivities start from 0, hence we have to check beforehand what is the connectivities offset + CoSimIO::ConnectivitiesType conn; for (const auto& r_elem : rModelPart.Elements()) { const auto& r_geom = r_elem.GetGeometry(); - DataBuffers::vector_types[elem_counter++] = geo_type_vtk_cell_type_map.at(r_geom.GetGeometryType()); // TODO add check + if (conn.size() != r_geom.PointsNumber()) { + conn.resize(r_geom.PointsNumber()); + }; - for (const auto& r_node : r_geom) { - const int current_id = r_node.Id(); - DataBuffers::vector_connectivities.push_back(current_id); - connectivities_offset = std::min(connectivities_offset, current_id); + for (std::size_t i=0; i 0) << "ModelPart is not empty, it has nodes!" << std::endl; KRATOS_ERROR_IF(rModelPart.NumberOfProperties() > 0) << "ModelPart is not empty, it has properties!" << std::endl; KRATOS_ERROR_IF(rModelPart.IsDistributed()) << "ModelPart cannot be distributed!" << std::endl; - const std::unordered_map> vtk_type_map = { - // {1 , "Element3D1N"}, // does not yet exist - {3 , {2, "Element2D2N"} }, // line - {5 , {3, "Element2D3N"} }, // triangle - {9 , {4, "Element2D4N"} }, // quad - {10 , {4, "Element3D4N"} }, // tetra - {12 , {8, "Element3D8N"} } // hexa - }; - - // fill ModelPart with received entities // TODO do this in OMP and add only after creation! - - for (std::size_t i=0; iId(), + (*node_it)->X(), + (*node_it)->Y(), + (*node_it)->Z() + ); + }; auto p_props = rModelPart.CreateNewProperties(0); - int counter=0; - for (std::size_t i=0; i elem_node_ids(num_nodes_elem); - for (int j=0; j conn; + for (auto elem_it=co_sim_io_model_part.ElementsBegin(); elem_it!=co_sim_io_model_part.ElementsEnd(); ++elem_it) { + if (conn.size() != (*elem_it)->NumberOfNodes()) { + conn.resize((*elem_it)->NumberOfNodes()); + }; + + const auto nodes_begin = (*elem_it)->NodesBegin(); + for (std::size_t i=0; i<(*elem_it)->NumberOfNodes(); ++i) { + conn[i] = (*(nodes_begin+i))->Id(); + }; + + rModelPart.CreateNewElement( + elem_name_map.at((*elem_it)->Type()), + (*elem_it)->Id(), + conn, + p_props + ); + }; } void ImportDataSizeCheck(const std::size_t ExpectedSize, const std::size_t ImportedSize) @@ -223,25 +248,24 @@ void ImportData_ModelPart_Vector( KRATOS_CATCH("") } -std::vector ImportData_RawValues( - CoSimIO::Info& rInfo) +void ImportData_RawValues( + CoSimIO::Info& rInfo, + CoSimIO::VectorWrapper& rValues) { KRATOS_TRY - CoSimIO::ImportData(rInfo, DataBuffers::vector_doubles); - - return DataBuffers::vector_doubles; + CoSimIO::ImportData(rInfo, rValues.Vector()); KRATOS_CATCH("") } void ExportData_RawValues( CoSimIO::Info& rInfo, - const std::vector& rValues) + const CoSimIO::VectorWrapper& rValues) { KRATOS_TRY - CoSimIO::ExportData(rInfo, rValues); + CoSimIO::ExportData(rInfo, rValues.Vector()); KRATOS_CATCH("") } @@ -269,29 +293,16 @@ void AddCoSimIOToPython(pybind11::module& m) auto m_co_sim_io = m.def_submodule("CoSimIO"); - py::class_(m_co_sim_io,"Info") - .def(py::init<>()) - .def("Has", &CoSimIO::Info::Has) - .def("GetInt", &CoSimIO::Info::Get) - .def("GetDouble", &CoSimIO::Info::Get) - .def("GetBool", &CoSimIO::Info::Get) - .def("GetString", &CoSimIO::Info::Get) - .def("SetInt", &CoSimIO::Info::Set) - .def("SetDouble", &CoSimIO::Info::Set) - .def("SetBool", &CoSimIO::Info::Set) - .def("SetString", &CoSimIO::Info::Set) - .def("Erase", &CoSimIO::Info::Erase) - .def("Clear", &CoSimIO::Info::Clear) - .def("Size", &CoSimIO::Info::Size) - .def("__str__", PrintObject); - ; + CoSimIO::AddCoSimIOInfoToPython(m_co_sim_io); + CoSimIO::AddCoSimIOConnectionStatusToPython(m_co_sim_io); + CoSimIO::AddCoSimIOVectorToPython(m_co_sim_io); + CoSimIO::AddCoSimIOVersionToPython(m_co_sim_io); - m_co_sim_io.def("Connect", &CoSimIO::Connect); + m_co_sim_io.def("Connect", &CoSimIO::Connect); m_co_sim_io.def("Disconnect", &CoSimIO::Disconnect); - m_co_sim_io.def("IsConverged", &CoSimIO::IsConverged); - - m_co_sim_io.def("SendControlSignal", CoSimIO::Internals::SendControlSignal); + m_co_sim_io.def("ImportInfo", &CoSimIO::ImportInfo); + m_co_sim_io.def("ExportInfo", &CoSimIO::ExportInfo); m_co_sim_io.def("ImportMesh", CoSimIO_Wrappers::ImportMesh); m_co_sim_io.def("ExportMesh", CoSimIO_Wrappers::ExportMesh); @@ -306,9 +317,6 @@ void AddCoSimIOToPython(pybind11::module& m) m_co_sim_io.def("InfoFromParameters", CoSimIO_Wrappers::InfoFromParameters); - // // m_co_sim_io.def("ImportGeometry", CoSimIO_Wrappers::ImportGeometry); // This is not yet implemented in the CoSimIO - // // m_co_sim_io.def("ExportGeometry", CoSimIO_Wrappers::ExportGeometry); // This is not yet implemented in the CoSimIO - py::enum_(m_co_sim_io,"DataLocation") .value("NodeHistorical", DataLocation::NodeHistorical) .value("NodeNonHistorical", DataLocation::NodeNonHistorical) @@ -317,31 +325,6 @@ void AddCoSimIOToPython(pybind11::module& m) .value("ModelPart", DataLocation::ModelPart) ; - py::enum_(m_co_sim_io,"ConnectionStatus") - .value("NotConnected",CoSimIO::ConnectionStatus::NotConnected) - .value("Connected",CoSimIO::ConnectionStatus::Connected) - .value("Disconnected", CoSimIO::ConnectionStatus::Disconnected) - .value("ConnectionError", CoSimIO::ConnectionStatus::ConnectionError) - .value("DisconnectionError", CoSimIO::ConnectionStatus::DisconnectionError) - ; - - py::enum_(m_co_sim_io,"ControlSignal") - .value("Dummy", CoSimIO::ControlSignal::Dummy) - // .value("BreakSolutionLoop", CoSimIO::ControlSignal::BreakSolutionLoop) - .value("ConvergenceAchieved", CoSimIO::ControlSignal::ConvergenceAchieved) - - // .value("AdvanceInTime", CoSimIO::ControlSignal::AdvanceInTime) - // .value("InitializeSolutionStep", CoSimIO::ControlSignal::InitializeSolutionStep) - // .value("SolveSolutionStep", CoSimIO::ControlSignal::SolveSolutionStep) - // .value("FinalizeSolutionStep", CoSimIO::ControlSignal::FinalizeSolutionStep) - - // .value("ImportGeometry", CoSimIO::ControlSignal::ImportGeometry) - // .value("ExportGeometry", CoSimIO::ControlSignal::ExportGeometry) - // .value("ImportMesh", CoSimIO::ControlSignal::ImportMesh) - // .value("ExportMesh", CoSimIO::ControlSignal::ExportMesh) - // .value("ImportData", CoSimIO::ControlSignal::ImportData) - // .value("ExportData", CoSimIO::ControlSignal::ExportData) - ; } } // namespace Python. diff --git a/applications/CoSimulationApplication/custom_python/add_custom_io_to_python.cpp b/applications/CoSimulationApplication/custom_python/add_custom_io_to_python.cpp index 537796a11693..ec865a1752f8 100644 --- a/applications/CoSimulationApplication/custom_python/add_custom_io_to_python.cpp +++ b/applications/CoSimulationApplication/custom_python/add_custom_io_to_python.cpp @@ -264,7 +264,7 @@ static void createModelPartFromReceivedMesh(const int numNodes, const int numEle KRATOS_ERROR_IF(rModelPart.IsDistributed()) << "ModelPart cannot be distributed!" << std::endl; const std::unordered_map element_name_map = { - // {1 , "Element3D1N"}, // does not yet exist + {1 , "Element3D1N"}, {2 , "Element3D2N"}, {3 , "Element3D3N"}, {4 , "Element3D4N"} diff --git a/applications/CoSimulationApplication/python_scripts/coupled_solvers/gauss_seidel_strong.py b/applications/CoSimulationApplication/python_scripts/coupled_solvers/gauss_seidel_strong.py index 7288e84196e5..1d089bd9a81e 100644 --- a/applications/CoSimulationApplication/python_scripts/coupled_solvers/gauss_seidel_strong.py +++ b/applications/CoSimulationApplication/python_scripts/coupled_solvers/gauss_seidel_strong.py @@ -98,16 +98,17 @@ def SolveSolutionStep(self): if is_converged: if self.echo_level > 0: cs_tools.cs_print_info(self._ClassName(), colors.green("### CONVERGENCE WAS ACHIEVED ###")) - self.__CommunicateStateOfConvergence(True) + self.__CommunicateIfTimeStepNeedsToBeRepeated(False) return True - if k+1 >= self.num_coupling_iterations and self.echo_level > 0: - cs_tools.cs_print_info(self._ClassName(), colors.red("XXX CONVERGENCE WAS NOT ACHIEVED XXX")) - self.__CommunicateStateOfConvergence(True) # True because max number of iterations is achieved. Otherwise external solver is stuck in time + if k+1 >= self.num_coupling_iterations: + if self.echo_level > 0: + cs_tools.cs_print_info(self._ClassName(), colors.red("XXX CONVERGENCE WAS NOT ACHIEVED XXX")) + self.__CommunicateIfTimeStepNeedsToBeRepeated(False) return False # if it reaches here it means that the coupling has not converged and this was not the last coupling iteration - self.__CommunicateStateOfConvergence(False) + self.__CommunicateIfTimeStepNeedsToBeRepeated(True) # do relaxation only if this iteration is not the last iteration of this timestep for conv_acc in self.convergence_accelerators_list: @@ -139,13 +140,13 @@ def _GetDefaultParameters(cls): return this_defaults - def __CommunicateStateOfConvergence(self, is_converged): - # Communicate the state of convergence with external solvers through IO - convergence_signal_config = { - "type" : "convergence_signal", - "is_converged" : is_converged + def __CommunicateIfTimeStepNeedsToBeRepeated(self, repeat_time_step): + # Communicate if the time step needs to be repeated with external solvers through IO + export_config = { + "type" : "repeat_time_step", + "repeat_time_step" : repeat_time_step } for solver in self.solver_wrappers.values(): - solver.ExportData(convergence_signal_config) + solver.ExportData(export_config) diff --git a/applications/CoSimulationApplication/python_scripts/solver_wrappers/empire_io.py b/applications/CoSimulationApplication/python_scripts/solver_wrappers/empire_io.py index 564ca7840d08..8bf87bd2f95c 100644 --- a/applications/CoSimulationApplication/python_scripts/solver_wrappers/empire_io.py +++ b/applications/CoSimulationApplication/python_scripts/solver_wrappers/empire_io.py @@ -70,8 +70,8 @@ def ExportData(self, data_config): if data_type == "coupling_interface_data": interface_data = data_config["interface_data"] KratosCoSim.EMPIRE_API.EMPIRE_API_sendDataField(interface_data.GetModelPart(), self.solver_name+"_"+interface_data.name, interface_data.variable) - elif data_type == "convergence_signal": - KratosCoSim.EMPIRE_API.EMPIRE_API_sendConvergenceSignal(data_config["is_converged"], self.solver_name) + elif data_type == "repeat_time_step": + KratosCoSim.EMPIRE_API.EMPIRE_API_sendConvergenceSignal((not data_config["repeat_time_step"]), self.solver_name) else: raise NotImplementedError('Exporting interface data of type "{}" is not implemented for this IO: "{}"'.format(data_type, self._ClassName())) diff --git a/applications/CoSimulationApplication/python_scripts/solver_wrappers/external/external_solver_wrapper.py b/applications/CoSimulationApplication/python_scripts/solver_wrappers/external/external_solver_wrapper.py index 5cdb412e164a..d697ff68ec19 100644 --- a/applications/CoSimulationApplication/python_scripts/solver_wrappers/external/external_solver_wrapper.py +++ b/applications/CoSimulationApplication/python_scripts/solver_wrappers/external/external_solver_wrapper.py @@ -21,7 +21,9 @@ def __init__(self, settings, model, solver_name): super(ExternalSolverWrapper, self).__init__(settings, model, solver_name) settings_defaults = KM.Parameters("""{ - "import_meshes" : [ ] + "import_meshes" : [ ], + "export_data" : [ ], + "import_data" : [ ] }""") self.settings["solver_wrapper_settings"].ValidateAndAssignDefaults(settings_defaults) @@ -39,5 +41,22 @@ def Initialize(self): def AdvanceInTime(self, current_time): return 0.0 # TODO find a better solution here... maybe get time from solver through IO + def SolveSolutionStep(self): + for data_name in self.settings["solver_wrapper_settings"]["export_data"].GetStringArray(): + data_config = { + "type" : "coupling_interface_data", + "interface_data" : self.GetInterfaceData(data_name) + } + self.ExportData(data_config) + + super().SolveSolutionStep() + + for data_name in self.settings["solver_wrapper_settings"]["import_data"].GetStringArray(): + data_config = { + "type" : "coupling_interface_data", + "interface_data" : self.GetInterfaceData(data_name) + } + self.ImportData(data_config) + def _GetIOType(self): return self.settings["io_settings"]["type"].GetString() \ No newline at end of file diff --git a/applications/CoSimulationApplication/python_scripts/solver_wrappers/kratos_co_sim_io.py b/applications/CoSimulationApplication/python_scripts/solver_wrappers/kratos_co_sim_io.py index d90cf7d9f5bf..6ec41a32e45c 100644 --- a/applications/CoSimulationApplication/python_scripts/solver_wrappers/kratos_co_sim_io.py +++ b/applications/CoSimulationApplication/python_scripts/solver_wrappers/kratos_co_sim_io.py @@ -15,18 +15,24 @@ class KratosCoSimIO(CoSimulationIO): """Wrapper for the CoSimIO to be used with Kratos """ def __init__(self, settings, model, solver_name): - super(KratosCoSimIO, self).__init__(settings, model, solver_name) + super().__init__(settings, model, solver_name) + + connect_to = self.settings["connect_to"].GetString() + if connect_to == "": + raise Exception('"connect_to" must be specified!') connection_settings = CoSimIO.InfoFromParameters(self.settings) - connection_settings.SetString("connection_name", solver_name) + connection_settings.SetString("my_name", solver_name) info = CoSimIO.Connect(connection_settings) if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Connected: raise Exception("Connecting failed!") + self.connection_name = info.GetString("connection_name") + def Finalize(self): disconnect_settings = CoSimIO.Info() - disconnect_settings.SetString("connection_name", self.solver_name) + disconnect_settings.SetString("connection_name", self.connection_name) info = CoSimIO.Disconnect(disconnect_settings) if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Disconnected: @@ -36,8 +42,8 @@ def ImportCouplingInterface(self, interface_config): model_part_name = interface_config["model_part_name"] info = CoSimIO.Info() - info.SetString("connection_name", self.solver_name) - info.SetString("identifier", model_part_name) + info.SetString("connection_name", self.connection_name) + info.SetString("identifier", model_part_name.replace(".", "-")) # TODO chec if better solution can be found CoSimIO.ImportMesh(info, self.model[model_part_name]) # TODO this can also be geometry at some point @@ -45,8 +51,8 @@ def ExportCouplingInterface(self, interface_config): model_part_name = interface_config["model_part_name"] info = CoSimIO.Info() - info.SetString("connection_name", self.solver_name) - info.SetString("identifier", model_part_name) + info.SetString("connection_name", self.connection_name) + info.SetString("identifier", model_part_name.replace(".", "-")) # TODO chec if better solution can be found CoSimIO.ExportMesh(info, self.model[model_part_name]) # TODO this can also be geometry at some point @@ -55,16 +61,10 @@ def ImportData(self, data_config): if data_type == "coupling_interface_data": interface_data = data_config["interface_data"] info = CoSimIO.Info() - info.SetString("connection_name", self.solver_name) + info.SetString("connection_name", self.connection_name) info.SetString("identifier", interface_data.name) CoSimIO.ImportData(info, interface_data.GetModelPart(), interface_data.variable, GetDataLocation(interface_data.location)) - - elif data_type == "time": - time_list = CoSimIO.ImportData(self.solver_name, "time_to_co_sim") - if len(time_list) != 1: - raise Exception("Wrong size received!") - data_config["time"] = time_list[0] else: raise NotImplementedError('Exporting interface data of type "{}" is not implemented for this IO: "{}"'.format(data_type, self._ClassName())) @@ -73,27 +73,18 @@ def ExportData(self, data_config): if data_type == "coupling_interface_data": interface_data = data_config["interface_data"] info = CoSimIO.Info() - info.SetString("connection_name", self.solver_name) + info.SetString("connection_name", self.connection_name) info.SetString("identifier", interface_data.name) CoSimIO.ExportData(info, interface_data.GetModelPart(), interface_data.variable, GetDataLocation(interface_data.location)) - elif data_type == "control_signal": - control_signal_key = data_config["signal"] - CoSimIO.SendControlSignal(self.solver_name, data_config["identifier"], control_signal_key) - - elif data_type == "time": - current_time = data_config["time"] - CoSimIO.ExportData(self.solver_name, "time_from_co_sim", [current_time]) - - elif data_type == "convergence_signal": - if data_config["is_converged"]: - control_signal_key = CoSimIO.ControlSignal.ConvergenceAchieved - else: - control_signal_key = CoSimIO.ControlSignal.Dummy + elif data_type == "repeat_time_step": info = CoSimIO.Info() - info.SetString("connection_name", self.solver_name) - CoSimIO.SendControlSignal(info, control_signal_key) + info.SetString("connection_name", self.connection_name) + info.SetString("identifier", "repeat_time_step_info") + info.SetBool("repeat_time_step", data_config["repeat_time_step"]) + + CoSimIO.ExportInfo(info) else: raise NotImplementedError('Exporting interface data of type "{}" is not implemented for this IO: "{}"'.format(data_type, self._ClassName())) @@ -106,11 +97,11 @@ def Check(self): @classmethod def _GetDefaultParameters(cls): this_defaults = KM.Parameters("""{ - "is_connection_master" : true, + "connect_to" : "", "communication_format" : "file", "print_timing" : false }""") - this_defaults.AddMissingParameters(super(KratosCoSimIO, cls)._GetDefaultParameters()) + this_defaults.AddMissingParameters(super()._GetDefaultParameters()) return this_defaults def GetDataLocation(location_str): diff --git a/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/connect_disconnect.py b/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/connect_disconnect.py index de028941559d..21e726ae40ee 100644 --- a/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/connect_disconnect.py +++ b/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/connect_disconnect.py @@ -1,14 +1,16 @@ from KratosMultiphysics.CoSimulationApplication import CoSimIO connection_settings = CoSimIO.Info() -connection_settings.SetString("connection_name", "c_d_test") -connection_settings.SetInt("echo_level", 0) +connection_settings.SetString("my_name", "partner_b") +connection_settings.SetString("connect_to", "partner_a") +connection_settings.SetInt("echo_level", 2) info = CoSimIO.Connect(connection_settings) +connection_name = info.GetString("connection_name") if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Connected: raise Exception("Connecting failed") disconnect_settings = CoSimIO.Info() -disconnect_settings.SetString("connection_name", "c_d_test") +disconnect_settings.SetString("connection_name", connection_name) info = CoSimIO.Disconnect(disconnect_settings) if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Disconnected: diff --git a/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/import_export_data.py b/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/import_export_data.py index e95fc1fc8e94..5ff618370c80 100644 --- a/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/import_export_data.py +++ b/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/import_export_data.py @@ -1,26 +1,29 @@ from KratosMultiphysics.CoSimulationApplication import CoSimIO connection_settings = CoSimIO.Info() -connection_settings.SetString("connection_name", "im_exp_data") +connection_settings.SetString("my_name", "impExp") +connection_settings.SetString("connect_to", "ExpImp") connection_settings.SetInt("echo_level", 0) info = CoSimIO.Connect(connection_settings) +connection_name = info.GetString("connection_name") if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Connected: raise Exception("Connecting failed") import_info = CoSimIO.Info() -import_info.SetString("connection_name", "im_exp_data") +import_info.SetString("connection_name", connection_name) import_info.SetString("identifier", "data_exchange_1") -imported_values = CoSimIO.ImportData(import_info) +imported_values = CoSimIO.DoubleVector() +CoSimIO.ImportData(import_info, imported_values) # print(imported_values) export_info = CoSimIO.Info() -export_info.SetString("connection_name", "im_exp_data") +export_info.SetString("connection_name", connection_name) export_info.SetString("identifier", "data_exchange_2") CoSimIO.ExportData(export_info, imported_values) disconnect_settings = CoSimIO.Info() -disconnect_settings.SetString("connection_name", "im_exp_data") +disconnect_settings.SetString("connection_name", connection_name) info = CoSimIO.Disconnect(disconnect_settings) if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Disconnected: diff --git a/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/import_export_mesh.py b/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/import_export_mesh.py index 82c4b977aed7..e30c8c988cae 100644 --- a/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/import_export_mesh.py +++ b/applications/CoSimulationApplication/tests/co_sim_io_py_exposure_aux_files/import_export_mesh.py @@ -5,26 +5,28 @@ model_part = model.CreateModelPart("mp_test") connection_settings = CoSimIO.Info() -connection_settings.SetString("connection_name", "im_exp_mesh") +connection_settings.SetString("my_name", "impExpMesh") +connection_settings.SetString("connect_to", "ExpImpMesh") connection_settings.SetInt("echo_level", 0) info = CoSimIO.Connect(connection_settings) +connection_name = info.GetString("connection_name") if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Connected: raise Exception("Connecting failed") import_info = CoSimIO.Info() -import_info.SetString("connection_name", "im_exp_mesh") +import_info.SetString("connection_name", connection_name) import_info.SetString("identifier", "mesh_exchange_1") CoSimIO.ImportMesh(import_info, model_part) # print(model_part) export_info = CoSimIO.Info() -export_info.SetString("connection_name", "im_exp_mesh") +export_info.SetString("connection_name", connection_name) export_info.SetString("identifier", "mesh_exchange_2") CoSimIO.ExportMesh(export_info, model_part) disconnect_settings = CoSimIO.Info() -disconnect_settings.SetString("connection_name", "im_exp_mesh") +disconnect_settings.SetString("connection_name", connection_name) info = CoSimIO.Disconnect(disconnect_settings) if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Disconnected: diff --git a/applications/CoSimulationApplication/tests/co_simulation_test_factory.py b/applications/CoSimulationApplication/tests/co_simulation_test_factory.py index 2cfe34ec6f07..5326d051884c 100644 --- a/applications/CoSimulationApplication/tests/co_simulation_test_factory.py +++ b/applications/CoSimulationApplication/tests/co_simulation_test_factory.py @@ -12,7 +12,7 @@ have_fsi_dependencies = kratos_utils.CheckIfApplicationsAvailable("FluidDynamicsApplication", "StructuralMechanicsApplication", "MappingApplication", "MeshMovingApplication", "LinearSolversApplication") have_potential_fsi_dependencies = kratos_utils.CheckIfApplicationsAvailable("CompressiblePotentialFlowApplication", "StructuralMechanicsApplication", "MappingApplication", "MeshMovingApplication", "LinearSolversApplication") -have_mpm_fem_dependencies = kratos_utils.CheckIfApplicationsAvailable("ParticleMechanicsApplication", "StructuralMechanicsApplication", "MappingApplication", "LinearSolversApplication") +have_mpm_fem_dependencies = kratos_utils.CheckIfApplicationsAvailable("ParticleMechanicsApplication", "StructuralMechanicsApplication", "MappingApplication", "LinearSolversApplication", "ConstitutiveLawsApplication") have_dem_fem_dependencies = kratos_utils.CheckIfApplicationsAvailable("DEMApplication", "StructuralMechanicsApplication", "MappingApplication", "LinearSolversApplication") have_fem_fem_dependencies = kratos_utils.CheckIfApplicationsAvailable("StructuralMechanicsApplication", "MappingApplication") diff --git a/applications/CoSimulationApplication/tests/fsi_mok/ProjectParametersCSM.json b/applications/CoSimulationApplication/tests/fsi_mok/ProjectParametersCSM.json index 14964576f19a..25bc265b8058 100644 --- a/applications/CoSimulationApplication/tests/fsi_mok/ProjectParametersCSM.json +++ b/applications/CoSimulationApplication/tests/fsi_mok/ProjectParametersCSM.json @@ -8,10 +8,11 @@ }, "co_sim_settings" : { "INFO" : "this block is only used if Kratos is used as an external solver for CoSimulation!", - "connection_name" : "structure", "is_strong_coupling" : true, "io_settings" : { - "echo_level" : 0 + "echo_level" : 0, + "my_name" : "ext_structure", + "connect_to" : "structure" }, "communication_settings" : { "export_meshes" : [ diff --git a/applications/CoSimulationApplication/tests/structural_mechanics_analysis_with_co_sim_io.py b/applications/CoSimulationApplication/tests/structural_mechanics_analysis_with_co_sim_io.py index 85aff96c13b7..bcbf6996df69 100644 --- a/applications/CoSimulationApplication/tests/structural_mechanics_analysis_with_co_sim_io.py +++ b/applications/CoSimulationApplication/tests/structural_mechanics_analysis_with_co_sim_io.py @@ -9,7 +9,7 @@ class StructuralMechanicsAnalysisWithCoSimIO(StructuralMechanicsAnalysis): '''Main script for structural mechanics with CoSimIO''' def __init__(self, model, parameters): - super(StructuralMechanicsAnalysisWithCoSimIO,self).__init__(model, parameters) + super().__init__(model, parameters) # To avoid many prints if (self.echo_level == 0): @@ -18,15 +18,14 @@ def __init__(self, model, parameters): KM.Logger.GetDefaultOutput().SetSeverity(KM.Logger.Severity.INFO) def Initialize(self): - super(StructuralMechanicsAnalysisWithCoSimIO, self).Initialize() + super().Initialize() self.co_sim_settings = self.project_parameters["co_sim_settings"] - self.connection_name = self.co_sim_settings["connection_name"].GetString() self.is_strong_coupling = self.co_sim_settings["is_strong_coupling"].GetBool() connection_settings = CoSimIO.InfoFromParameters(self.project_parameters["co_sim_settings"]["io_settings"]) - connection_settings.SetString("connection_name", self.connection_name) info = CoSimIO.Connect(connection_settings) + self.connection_name = info.GetString("connection_name") if info.GetInt("connection_status") != CoSimIO.ConnectionStatus.Connected: raise Exception("Connecting failed!") @@ -36,7 +35,7 @@ def Initialize(self): for model_part_name in self.communication_settings["export_meshes"].GetStringArray(): info = CoSimIO.Info() info.SetString("connection_name", self.connection_name) - info.SetString("identifier", model_part_name) + info.SetString("identifier", model_part_name.replace(".", "-")) CoSimIO.ExportMesh(info, self.model[model_part_name]) @@ -80,13 +79,14 @@ def RunSolutionLoop(self): self._GetSolver().Predict() if self.is_strong_coupling: - is_converged = False - while not is_converged: + repeat_time_step = True + while repeat_time_step: self.__InnerLoop() info = CoSimIO.Info() info.SetString("connection_name", self.connection_name) - is_converged_info = CoSimIO.IsConverged(info) - is_converged = is_converged_info.GetBool("is_converged") + info.SetString("identifier", "repeat_time_step_info") + repeat_time_step_info = CoSimIO.ImportInfo(info) + repeat_time_step = repeat_time_step_info.GetBool("repeat_time_step") else: self.__InnerLoop() @@ -94,7 +94,7 @@ def RunSolutionLoop(self): self.OutputSolutionStep() def Finalize(self): - super(StructuralMechanicsAnalysisWithCoSimIO, self).Finalize() + super().Finalize() disconnect_settings = CoSimIO.Info() disconnect_settings.SetString("connection_name", self.connection_name) diff --git a/applications/CoSimulationApplication/tests/test_CoSimulationApplication.py b/applications/CoSimulationApplication/tests/test_CoSimulationApplication.py index e04c465ebc42..e35aa70051de 100644 --- a/applications/CoSimulationApplication/tests/test_CoSimulationApplication.py +++ b/applications/CoSimulationApplication/tests/test_CoSimulationApplication.py @@ -1,6 +1,5 @@ # Import Kratos "wrapper" for unittests import KratosMultiphysics.KratosUnittest as KratosUnittest -import os try: import numpy @@ -80,9 +79,7 @@ def AssembleTestSuites(): nightSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestSmallCoSimulationCases])) nightSuite.addTest(TestMokFSI('test_mok_fsi_mvqn')) nightSuite.addTest(TestMokFSI('test_mok_fsi_aitken')) - if os.name != "nt": - # currently those tests don#t work in win - nightSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestCoSimIOPyExposure])) + nightSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestCoSimIOPyExposure])) nightSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestKratosCoSimIO])) nightSuite.addTests(smallSuite) @@ -91,7 +88,7 @@ def AssembleTestSuites(): # For very long tests that should not be in nighly and you can use to validate validationSuite = suites['validation'] validationSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestCoSimulationCases])) - # validationSuite.addTest(TestMokFSI('test_mok_fsi_mvqn_external_structure')) + validationSuite.addTest(TestMokFSI('test_mok_fsi_mvqn_external_structure')) # if numpy_available: # validationSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestFLOWerCoupling])) diff --git a/applications/CoSimulationApplication/tests/test_co_sim_io_py_exposure.py b/applications/CoSimulationApplication/tests/test_co_sim_io_py_exposure.py index b80350f64119..208192a6a0cb 100644 --- a/applications/CoSimulationApplication/tests/test_co_sim_io_py_exposure.py +++ b/applications/CoSimulationApplication/tests/test_co_sim_io_py_exposure.py @@ -41,48 +41,57 @@ def test_InfoFromParameters(self): class TestCoSimIOPyExposure(KratosUnittest.TestCase): def test_Connect_Disconnect(self): + p = self.__RunPythonInSubProcess("connect_disconnect") + connection_settings = CoSimIO.Info() - connection_settings.SetString("connection_name", "c_d_test") + connection_settings.SetString("my_name", "partner_a") + connection_settings.SetString("connect_to", "partner_b") connection_settings.SetInt("echo_level", 0) info = CoSimIO.Connect(connection_settings) + connection_name = info.GetString("connection_name") self.assertEqual(info.GetInt("connection_status"), CoSimIO.ConnectionStatus.Connected) - RunPythonInSubProcess("connect_disconnect") - disconnect_settings = CoSimIO.Info() - disconnect_settings.SetString("connection_name", "c_d_test") + disconnect_settings.SetString("connection_name", connection_name) info = CoSimIO.Disconnect(disconnect_settings) self.assertEqual(info.GetInt("connection_status"), CoSimIO.ConnectionStatus.Disconnected) + self.__CheckSubProcess(p) + def test_Export_Import_Data_raw_values(self): + p = self.__RunPythonInSubProcess("import_export_data") + connection_settings = CoSimIO.Info() - connection_settings.SetString("connection_name", "im_exp_data") + connection_settings.SetString("my_name", "ExpImp") + connection_settings.SetString("connect_to", "impExp") connection_settings.SetInt("echo_level", 0) info = CoSimIO.Connect(connection_settings) + connection_name = info.GetString("connection_name") self.assertEqual(info.GetInt("connection_status"), CoSimIO.ConnectionStatus.Connected) - values = [1.0, 2.5, 3.3, -9.4] + values = CoSimIO.DoubleVector([1.0, 2.5, 3.3, -9.4]) export_info = CoSimIO.Info() - export_info.SetString("connection_name", "im_exp_data") + export_info.SetString("connection_name", connection_name) export_info.SetString("identifier", "data_exchange_1") CoSimIO.ExportData(export_info, values) - RunPythonInSubProcess("import_export_data") - import_info = CoSimIO.Info() - import_info.SetString("connection_name", "im_exp_data") + import_info.SetString("connection_name", connection_name) import_info.SetString("identifier", "data_exchange_2") - imported_values = CoSimIO.ImportData(import_info) + imported_values = CoSimIO.DoubleVector() + CoSimIO.ImportData(import_info, imported_values) disconnect_settings = CoSimIO.Info() - disconnect_settings.SetString("connection_name", "im_exp_data") + disconnect_settings.SetString("connection_name", connection_name) info = CoSimIO.Disconnect(disconnect_settings) self.assertEqual(info.GetInt("connection_status"), CoSimIO.ConnectionStatus.Disconnected) # checking the values after disconnecting to avoid deadlock - self.assertVectorAlmostEqual(KM.Vector(values), KM.Vector(imported_values)) + self.assertVectorAlmostEqual(values, imported_values) + + self.__CheckSubProcess(p) def test_Export_Import_Data_ModelPart_scalar_node_historical(self): model = KM.Model() @@ -237,6 +246,8 @@ def test_Export_Import_Data_ModelPart_vector_model_part(self): self.assertVectorAlmostEqual(model_part.GetValue(KM.VELOCITY), KM.Vector([14.3, -333.896, 987.2])) def test_Export_Import_Mesh(self): + p = self.__RunPythonInSubProcess("import_export_mesh") + model = KM.Model() model_part = model.CreateModelPart("for_test") @@ -249,34 +260,37 @@ def test_Export_Import_Mesh(self): model_part.CreateNewElement("Element2D2N", i+1, [i+1, i+2], props) connection_settings = CoSimIO.Info() - connection_settings.SetString("connection_name", "im_exp_mesh") + connection_settings.SetString("my_name", "ExpImpMesh") + connection_settings.SetString("connect_to", "impExpMesh") connection_settings.SetInt("echo_level", 0) info = CoSimIO.Connect(connection_settings) + connection_name = info.GetString("connection_name") self.assertEqual(info.GetInt("connection_status"), CoSimIO.ConnectionStatus.Connected) export_info = CoSimIO.Info() - export_info.SetString("connection_name", "im_exp_mesh") + export_info.SetString("connection_name", connection_name) export_info.SetString("identifier", "mesh_exchange_1") CoSimIO.ExportMesh(export_info, model_part) - RunPythonInSubProcess("import_export_mesh") - import_info = CoSimIO.Info() - import_info.SetString("connection_name", "im_exp_mesh") + import_info.SetString("connection_name", connection_name) import_info.SetString("identifier", "mesh_exchange_2") CoSimIO.ImportMesh(import_info, model_part_returned) disconnect_settings = CoSimIO.Info() - disconnect_settings.SetString("connection_name", "im_exp_mesh") + disconnect_settings.SetString("connection_name", connection_name) info = CoSimIO.Disconnect(disconnect_settings) self.assertEqual(info.GetInt("connection_status"), CoSimIO.ConnectionStatus.Disconnected) + self.__CheckSubProcess(p) + # checking the values after disconnecting to avoid deadlock self.assertEqual(model_part.NumberOfNodes(), model_part_returned.NumberOfNodes()) self.assertEqual(model_part.NumberOfElements(), model_part_returned.NumberOfElements()) for node_orig, node_exchanged in zip(model_part.Nodes, model_part_returned.Nodes): + self.assertEqual(node_orig.Id, node_exchanged.Id) self.assertAlmostEqual(node_orig.X0, node_exchanged.X0) self.assertAlmostEqual(node_orig.Y0, node_exchanged.Y0) self.assertAlmostEqual(node_orig.Z0, node_exchanged.Z0) @@ -284,44 +298,56 @@ def test_Export_Import_Mesh(self): for elem_orig, elem_exchanged in zip(model_part.Elements, model_part_returned.Elements): self.assertEqual(len(elem_orig.GetNodes()), len(elem_exchanged.GetNodes())) for node_orig, node_exchanged in zip(elem_orig.GetNodes(), elem_exchanged.GetNodes()): + self.assertEqual(node_orig.Id, node_exchanged.Id) self.assertAlmostEqual(node_orig.X0, node_exchanged.X0) self.assertAlmostEqual(node_orig.Y0, node_exchanged.Y0) self.assertAlmostEqual(node_orig.Z0, node_exchanged.Z0) def __ExportImportDataOnModelPart(self, model_part, var_export, var_import, data_location): + p = self.__RunPythonInSubProcess("import_export_data") + connection_settings = CoSimIO.Info() - connection_settings.SetString("connection_name", "im_exp_data") + connection_settings.SetString("my_name", "ExpImp") + connection_settings.SetString("connect_to", "impExp") connection_settings.SetInt("echo_level", 0) info = CoSimIO.Connect(connection_settings) + connection_name = info.GetString("connection_name") self.assertEqual(info.GetInt("connection_status"), CoSimIO.ConnectionStatus.Connected) export_info = CoSimIO.Info() - export_info.SetString("connection_name", "im_exp_data") + export_info.SetString("connection_name", connection_name) export_info.SetString("identifier", "data_exchange_1") CoSimIO.ExportData(export_info, model_part, var_export, data_location) - RunPythonInSubProcess("import_export_data") - import_info = CoSimIO.Info() - import_info.SetString("connection_name", "im_exp_data") + import_info.SetString("connection_name", connection_name) import_info.SetString("identifier", "data_exchange_2") CoSimIO.ImportData(import_info, model_part, var_import, data_location) disconnect_settings = CoSimIO.Info() - disconnect_settings.SetString("connection_name", "im_exp_data") + disconnect_settings.SetString("connection_name", connection_name) info = CoSimIO.Disconnect(disconnect_settings) self.assertEqual(info.GetInt("connection_status"), CoSimIO.ConnectionStatus.Disconnected) -def RunPythonInSubProcess(python_script_name): - if not python_script_name.endswith(".py"): - python_script_name += ".py" + self.__CheckSubProcess(p) + + + def __RunPythonInSubProcess(self, script_name): + if not script_name.endswith(".py"): + script_name += ".py" + + return subprocess.Popen([GetPython3Command(), os.path.join("co_sim_io_py_exposure_aux_files", script_name)], stdout=subprocess.PIPE) - py_cmd = GetPython3Command() + def __CheckSubProcess(self, proc): + try: + p_out = proc.communicate(timeout=5) + except subprocess.TimeoutExpired: # Timeout reached + proc.kill() + p_out = proc.communicate() - cmd_list = [py_cmd, os.path.join("co_sim_io_py_exposure_aux_files", python_script_name)] - subprocess.run(cmd_list, check=True, shell=os.name=="nt") # crashes the calling script too, otherwise the error is silent (using shell in Win) + self.assertEqual(proc.returncode, 0, msg=p_out[0].decode('ascii')) if __name__ == '__main__': diff --git a/applications/CoSimulationApplication/tests/test_kratos_co_sim_io.py b/applications/CoSimulationApplication/tests/test_kratos_co_sim_io.py index cb1bcaddc500..88372c97289a 100644 --- a/applications/CoSimulationApplication/tests/test_kratos_co_sim_io.py +++ b/applications/CoSimulationApplication/tests/test_kratos_co_sim_io.py @@ -12,20 +12,27 @@ class TestKratosCoSimIO(KratosUnittest.TestCase): def test_Connect_Disconnect(self): + p = self.__RunPythonInSubProcess("connect_disconnect") model = KM.Model() - io_settings = KM.Parameters("""{}""") # using the defaults - solver_name = "c_d_test" + io_settings = KM.Parameters("""{ + "connect_to" : "partner_b" + }""") + solver_name = "partner_a" # aka "my_name" for the CoSimIO kratos_co_sim_io = CreateKratosCoSimIO(io_settings, model, solver_name) # this connects kratos_co_sim_io.Initialize() - RunPythonInSubProcess("connect_disconnect") - kratos_co_sim_io.Finalize() # this disconnects + self.__CheckSubProcess(p) + def test_Export_ImportCouplingData(self): + p = self.__RunPythonInSubProcess("import_export_data") + model = KM.Model() - io_settings = KM.Parameters("""{}""") # using the defaults - solver_name = "im_exp_data" + io_settings = KM.Parameters("""{ + "connect_to" : "impExp" + }""") + solver_name = "ExpImp" # aka "my_name" for the CoSimIO kratos_co_sim_io = CreateKratosCoSimIO(io_settings, model, solver_name) # this connects kratos_co_sim_io.Initialize() @@ -53,8 +60,6 @@ def test_Export_ImportCouplingData(self): data_configuration_export = {"type" : "coupling_interface_data", "interface_data" : interface_data_pres} kratos_co_sim_io.ExportData(data_configuration_export) - RunPythonInSubProcess("import_export_data") - data_configuration_import = {"type" : "coupling_interface_data", "interface_data" : interface_data_temp} kratos_co_sim_io.ImportData(data_configuration_import) @@ -64,10 +69,16 @@ def test_Export_ImportCouplingData(self): for i, node in enumerate(model_part.Nodes): self.assertAlmostEqual(node.GetSolutionStepValue(KM.TEMPERATURE), i*1.7) + self.__CheckSubProcess(p) + def test_Export_ImportCouplingInterface_Mesh(self): # can also be Geometry at some point + p = self.__RunPythonInSubProcess("import_export_mesh") + model = KM.Model() - io_settings = KM.Parameters("""{}""") # using the defaults - solver_name = "im_exp_mesh" + io_settings = KM.Parameters("""{ + "connect_to" : "impExpMesh" + }""") + solver_name = "ExpImpMesh" # aka "my_name" for the CoSimIO kratos_co_sim_io = CreateKratosCoSimIO(io_settings, model, solver_name) # this connects kratos_co_sim_io.Initialize() @@ -83,8 +94,6 @@ def test_Export_ImportCouplingInterface_Mesh(self): # can also be Geometry at so interface_configuration_export = {"model_part_name" : "mesh_exchange_1"} kratos_co_sim_io.ExportCouplingInterface(interface_configuration_export) - RunPythonInSubProcess("import_export_mesh") - interface_configuration_import = {"model_part_name" : "mesh_exchange_2"} kratos_co_sim_io.ImportCouplingInterface(interface_configuration_import) @@ -95,6 +104,7 @@ def test_Export_ImportCouplingInterface_Mesh(self): # can also be Geometry at so self.assertEqual(model_part.NumberOfElements(), model_part_returned.NumberOfElements()) for node_orig, node_exchanged in zip(model_part.Nodes, model_part_returned.Nodes): + self.assertEqual(node_orig.Id, node_exchanged.Id) self.assertAlmostEqual(node_orig.X0, node_exchanged.X0) self.assertAlmostEqual(node_orig.Y0, node_exchanged.Y0) self.assertAlmostEqual(node_orig.Z0, node_exchanged.Z0) @@ -102,19 +112,28 @@ def test_Export_ImportCouplingInterface_Mesh(self): # can also be Geometry at so for elem_orig, elem_exchanged in zip(model_part.Elements, model_part_returned.Elements): self.assertEqual(len(elem_orig.GetNodes()), len(elem_exchanged.GetNodes())) for node_orig, node_exchanged in zip(elem_orig.GetNodes(), elem_exchanged.GetNodes()): + self.assertEqual(node_orig.Id, node_exchanged.Id) self.assertAlmostEqual(node_orig.X0, node_exchanged.X0) self.assertAlmostEqual(node_orig.Y0, node_exchanged.Y0) self.assertAlmostEqual(node_orig.Z0, node_exchanged.Z0) + self.__CheckSubProcess(p) + + + def __RunPythonInSubProcess(self, script_name): + if not script_name.endswith(".py"): + script_name += ".py" -def RunPythonInSubProcess(python_script_name): - if not python_script_name.endswith(".py"): - python_script_name += ".py" + return subprocess.Popen([GetPython3Command(), os.path.join("co_sim_io_py_exposure_aux_files", script_name)], stdout=subprocess.PIPE) - py_cmd = GetPython3Command() + def __CheckSubProcess(self, proc): + try: + p_out = proc.communicate(timeout=5) + except subprocess.TimeoutExpired: # Timeout reached + proc.kill() + p_out = proc.communicate() - cmd_list = [py_cmd, os.path.join("co_sim_io_py_exposure_aux_files", python_script_name)] - subprocess.run(cmd_list, check=True, shell=os.name=="nt") # crashes the calling script too, otherwise the error is silent (using shell in Win) + self.assertEqual(proc.returncode, 0, msg=p_out[0].decode('ascii')) if __name__ == '__main__': diff --git a/applications/CoSimulationApplication/tests/test_mok_fsi.py b/applications/CoSimulationApplication/tests/test_mok_fsi.py index 064526520d8c..a463aad7fa53 100644 --- a/applications/CoSimulationApplication/tests/test_mok_fsi.py +++ b/applications/CoSimulationApplication/tests/test_mok_fsi.py @@ -1,8 +1,8 @@ -from __future__ import print_function, absolute_import, division import KratosMultiphysics as KM import KratosMultiphysics.KratosUnittest as KratosUnittest import KratosMultiphysics.kratos_utilities as kratos_utils +from KratosMultiphysics.testing.utilities import GetPython3Command import co_simulation_test_case import os @@ -60,7 +60,7 @@ def test_mok_fsi_mvqn_external_structure(self): self.__RemoveOutputFromCFD() # comment to get output self.__AddTestingToCFD() self.__DumpUpdatedCFDSettings() - self._runTestWithExternal(["python3", "structural_mechanics_analysis_with_co_sim_io.py", ext_parameter_file_name]) + self._runTestWithExternal([GetPython3Command(), "structural_mechanics_analysis_with_co_sim_io.py", ext_parameter_file_name]) def __ManipulateSettings(self, external_structure=False): self.cosim_parameters["solver_settings"]["convergence_accelerators"][0]["type"].SetString(self.accelerator_type) @@ -71,8 +71,16 @@ def __ManipulateSettings(self, external_structure=False): structure_settings.RemoveValue("solver_wrapper_settings") structure_settings["type"].SetString("solver_wrappers.external.external_solver_wrapper") - solver_wrapper_settings = KM.Parameters("""{ "import_meshes" : ["Structure.GENERIC_FSI"] }""") - io_settings = KM.Parameters("""{ "type" : "kratos_co_sim_io" }""") + solver_wrapper_settings = KM.Parameters("""{ + "import_meshes" : ["Structure.GENERIC_FSI"], + "export_data" : ["load"], + "import_data" : ["disp"] + }""") + io_settings = KM.Parameters("""{ + "type" : "kratos_co_sim_io", + "echo_level" : 3, + "connect_to" : "ext_structure" + }""") structure_settings.AddValue("solver_wrapper_settings", solver_wrapper_settings) structure_settings.AddValue("io_settings", io_settings) diff --git a/applications/CompressiblePotentialFlowApplication/CMakeLists.txt b/applications/CompressiblePotentialFlowApplication/CMakeLists.txt index 16f01014ff7e..b6ffe3764dd8 100644 --- a/applications/CompressiblePotentialFlowApplication/CMakeLists.txt +++ b/applications/CompressiblePotentialFlowApplication/CMakeLists.txt @@ -39,6 +39,12 @@ pybind11_add_module(KratosCompressiblePotentialFlowApplication MODULE THIN_LTO $ target_link_libraries(KratosCompressiblePotentialFlowApplication PRIVATE KratosCompressiblePotentialFlowCore ) set_target_properties(KratosCompressiblePotentialFlowApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosCompressiblePotentialFlowCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosCompressiblePotentialFlowApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosCompressiblePotentialFlowApplication PROPERTIES SUFFIX .pyd) @@ -49,12 +55,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosCompressiblePotentialFlowApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosCompressiblePotentialFlowCore) - cotire(KratosCompressiblePotentialFlowApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/CompressiblePotentialFlowApplication.py KratosMultiphysics/CompressiblePotentialFlowApplication/__init__.py ) diff --git a/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application.cpp b/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application.cpp index 26a90e96c7f2..592cacef32a4 100644 --- a/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application.cpp +++ b/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application.cpp @@ -105,6 +105,9 @@ void KratosCompressiblePotentialFlowApplication::Register() KRATOS_REGISTER_VARIABLE(CRITICAL_MACH) KRATOS_REGISTER_VARIABLE(UPWIND_FACTOR_CONSTANT) + // Solver settings + KRATOS_REGISTER_VARIABLE(ECHO_LEVEL) + // Markers KRATOS_REGISTER_VARIABLE(WAKE); KRATOS_REGISTER_VARIABLE(KUTTA); diff --git a/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application_variables.cpp b/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application_variables.cpp index 8234c418fbdc..ce63dccc9703 100644 --- a/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application_variables.cpp +++ b/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application_variables.cpp @@ -51,6 +51,9 @@ KRATOS_CREATE_VARIABLE(double, MACH_SQUARED_LIMIT) KRATOS_CREATE_VARIABLE(double, CRITICAL_MACH) KRATOS_CREATE_VARIABLE(double, UPWIND_FACTOR_CONSTANT) +// Solver settings +KRATOS_CREATE_VARIABLE(int, ECHO_LEVEL) + // Markers KRATOS_CREATE_VARIABLE(int, WAKE) KRATOS_CREATE_VARIABLE(int, KUTTA) diff --git a/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application_variables.h b/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application_variables.h index 2661b0ec9dad..30174207d473 100644 --- a/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application_variables.h +++ b/applications/CompressiblePotentialFlowApplication/compressible_potential_flow_application_variables.h @@ -74,6 +74,9 @@ KRATOS_DEFINE_APPLICATION_VARIABLE(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION, doub KRATOS_DEFINE_APPLICATION_VARIABLE(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION, double, CRITICAL_MACH) KRATOS_DEFINE_APPLICATION_VARIABLE(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION, double, UPWIND_FACTOR_CONSTANT) +// Solver settings +KRATOS_DEFINE_APPLICATION_VARIABLE(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION, int, ECHO_LEVEL) + // Markers KRATOS_DEFINE_APPLICATION_VARIABLE(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION, int, WAKE) KRATOS_DEFINE_APPLICATION_VARIABLE(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION, int, KUTTA) diff --git a/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_perturbation_potential_flow_element.cpp b/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_perturbation_potential_flow_element.cpp index dcd822615afe..1aa96d7bb484 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_perturbation_potential_flow_element.cpp +++ b/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_perturbation_potential_flow_element.cpp @@ -200,7 +200,11 @@ void CompressiblePerturbationPotentialFlowElement::CalculateOnInt } else if (rVariable == DENSITY) { - rValues[0] = ComputeDensity(rCurrentProcessInfo); + const array_1d& velocity = PotentialFlowUtilities::ComputePerturbedVelocity(*this, rCurrentProcessInfo); + + const double local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(velocity, rCurrentProcessInfo); + + rValues[0] = PotentialFlowUtilities::ComputeDensity(local_mach_number_squared, rCurrentProcessInfo); } else if (rVariable == MACH) { @@ -409,24 +413,13 @@ void CompressiblePerturbationPotentialFlowElement::CalculateLeftH // Calculate shape functions GeometryUtils::CalculateGeometryData(GetGeometry(), data.DN_DX, data.N, data.vol); - const double density = ComputeDensity(rCurrentProcessInfo); - const double DrhoDu2 = ComputeDensityDerivative(density, rCurrentProcessInfo); - - // Computing local velocity - const array_1d free_stream_velocity = rCurrentProcessInfo[FREE_STREAM_VELOCITY]; - array_1d velocity = PotentialFlowUtilities::ComputeVelocity(*this); - for (unsigned int i = 0; i < Dim; i++){ - velocity[i] += free_stream_velocity[i]; - } + const array_1d& velocity = PotentialFlowUtilities::ComputePerturbedVelocity(*this, rCurrentProcessInfo); - const BoundedVector DNV = prod(data.DN_DX, velocity); + BoundedMatrix lhs = ZeroMatrix(NumNodes,NumNodes); - noalias(rLeftHandSideMatrix) += - data.vol * density * prod(data.DN_DX, trans(data.DN_DX)); - noalias(rLeftHandSideMatrix) += data.vol * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + CalculateLeftHandSideContribution(lhs, rCurrentProcessInfo, velocity, data); - const BoundedMatrix rLaplacianMatrix = - data.vol * density * prod(data.DN_DX, trans(data.DN_DX)); + noalias(rLeftHandSideMatrix) = lhs; } template @@ -442,16 +435,14 @@ void CompressiblePerturbationPotentialFlowElement::CalculateRight // Calculate shape functions GeometryUtils::CalculateGeometryData(GetGeometry(), data.DN_DX, data.N, data.vol); - const double density = ComputeDensity(rCurrentProcessInfo); + const CompressiblePerturbationPotentialFlowElement& r_this = *this; - // Computing local velocity - const array_1d free_stream_velocity = rCurrentProcessInfo[FREE_STREAM_VELOCITY]; - array_1d velocity = PotentialFlowUtilities::ComputeVelocity(*this); - for (unsigned int i = 0; i < Dim; i++){ - velocity[i] += free_stream_velocity[i]; - } + array_1d velocity = PotentialFlowUtilities::ComputePerturbedVelocity(r_this, rCurrentProcessInfo); - noalias(rRightHandSideVector) = - data.vol * density * prod(data.DN_DX, velocity); + BoundedVector rhs = ZeroVector(NumNodes); + CalculateRightHandSideContribution(rhs, rCurrentProcessInfo, velocity, data); + + noalias(rRightHandSideVector) = rhs; } template @@ -470,21 +461,19 @@ void CompressiblePerturbationPotentialFlowElement::CalculateLeftH GeometryUtils::CalculateGeometryData(GetGeometry(), data.DN_DX, data.N, data.vol); GetWakeDistances(data.distances); - const double density = ComputeDensity(rCurrentProcessInfo); - const double DrhoDu2 = ComputeDensityDerivative(density, rCurrentProcessInfo); + // Compute upper and lower velocities + const array_1d& upper_velocity = PotentialFlowUtilities::ComputePerturbedVelocity(*this, rCurrentProcessInfo); + const array_1d& lower_velocity = PotentialFlowUtilities::ComputePerturbedVelocityLowerElement(*this, rCurrentProcessInfo); - // Computing local velocity - const array_1d free_stream_velocity = rCurrentProcessInfo[FREE_STREAM_VELOCITY]; - array_1d velocity = PotentialFlowUtilities::ComputeVelocity(*this); - for (unsigned int i = 0; i < Dim; i++){ - velocity[i] += free_stream_velocity[i]; - } + BoundedMatrix upper_lhs_total = ZeroMatrix(NumNodes,NumNodes); + BoundedMatrix lower_lhs_total = ZeroMatrix(NumNodes,NumNodes); - const BoundedVector DNV = prod(data.DN_DX, velocity); + CalculateLeftHandSideContribution(upper_lhs_total, rCurrentProcessInfo, upper_velocity, data); + CalculateLeftHandSideContribution(lower_lhs_total, rCurrentProcessInfo, lower_velocity, data); - const BoundedMatrix lhs_total = - data.vol * density * prod(data.DN_DX, trans(data.DN_DX)) + - data.vol * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + // Compute lhs wake condition + const double free_stream_density = rCurrentProcessInfo[FREE_STREAM_DENSITY]; + const BoundedMatrix lhs_wake_condition = data.vol * free_stream_density * prod(data.DN_DX, trans(data.DN_DX)); if (this->Is(STRUCTURE)){ Matrix lhs_positive = ZeroMatrix(NumNodes, NumNodes); @@ -492,10 +481,10 @@ void CompressiblePerturbationPotentialFlowElement::CalculateLeftH CalculateLeftHandSideSubdividedElement(lhs_positive, lhs_negative, rCurrentProcessInfo); AssignLeftHandSideSubdividedElement(rLeftHandSideMatrix, lhs_positive, - lhs_negative, lhs_total, data); + lhs_negative, upper_lhs_total, lower_lhs_total, lhs_wake_condition, data); } else{ - AssignLeftHandSideWakeElement(rLeftHandSideMatrix, lhs_total, data); + AssignLeftHandSideWakeElement(rLeftHandSideMatrix, upper_lhs_total, lower_lhs_total, lhs_wake_condition, data); } } @@ -515,21 +504,21 @@ void CompressiblePerturbationPotentialFlowElement::CalculateRight GeometryUtils::CalculateGeometryData(r_geometry, data.DN_DX, data.N, data.vol); GetWakeDistances(data.distances); - const double density = ComputeDensity(rCurrentProcessInfo); + // Compute upper and lower velocities + const array_1d& upper_velocity = PotentialFlowUtilities::ComputePerturbedVelocity(*this, rCurrentProcessInfo); + const array_1d& lower_velocity = PotentialFlowUtilities::ComputePerturbedVelocityLowerElement(*this, rCurrentProcessInfo); - const array_1d free_stream_velocity = rCurrentProcessInfo[FREE_STREAM_VELOCITY]; - array_1d upper_velocity = PotentialFlowUtilities::ComputeVelocityUpperWakeElement(*this); - array_1d lower_velocity = PotentialFlowUtilities::ComputeVelocityLowerWakeElement(*this); + // Compute upper and lower rhs + BoundedVector upper_rhs = ZeroVector(NumNodes); + BoundedVector lower_rhs = ZeroVector(NumNodes); + CalculateRightHandSideContribution(upper_rhs, rCurrentProcessInfo, upper_velocity, data); + CalculateRightHandSideContribution(lower_rhs, rCurrentProcessInfo, lower_velocity, data); - for (unsigned int i = 0; i < Dim; i++){ - upper_velocity[i] += free_stream_velocity[i]; - lower_velocity[i] += free_stream_velocity[i]; - } - const array_1d diff_velocity = upper_velocity - lower_velocity; + const array_1d& diff_velocity = upper_velocity - lower_velocity; - const BoundedVector upper_rhs = - data.vol * density * prod(data.DN_DX, upper_velocity); - const BoundedVector lower_rhs = - data.vol * density * prod(data.DN_DX, lower_velocity); - const BoundedVector wake_rhs = - data.vol * density * prod(data.DN_DX, diff_velocity); + // Compute wake condition rhs + const double free_stream_density = rCurrentProcessInfo[FREE_STREAM_DENSITY]; + const BoundedVector wake_rhs = - data.vol * free_stream_density * prod(data.DN_DX, diff_velocity); if (this->Is(STRUCTURE)){ double upper_vol = 0.0; @@ -553,6 +542,47 @@ void CompressiblePerturbationPotentialFlowElement::CalculateRight } } +template +void CompressiblePerturbationPotentialFlowElement::CalculateLeftHandSideContribution( + BoundedMatrix& rLhs_total, + const ProcessInfo& rCurrentProcessInfo, + const array_1d& rVelocity, + const ElementalData& rData) +{ + // Compute density + const double local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(rVelocity, rCurrentProcessInfo); + const double density = PotentialFlowUtilities::ComputeDensity(local_mach_number_squared, rCurrentProcessInfo); + + // Compute density derivative + const double DrhoDu2 = PotentialFlowUtilities::ComputeDensityDerivativeWRTVelocitySquared(local_mach_number_squared, rCurrentProcessInfo); + + // Compute lhs + const BoundedVector DNV = prod(rData.DN_DX, rVelocity); + + rLhs_total = rData.vol * density * prod(rData.DN_DX, trans(rData.DN_DX)); + + const double local_velocity_squared = inner_prod(rVelocity, rVelocity); + + const double max_velocity_squared = PotentialFlowUtilities::ComputeMaximumVelocitySquared(rCurrentProcessInfo); + if (local_velocity_squared < max_velocity_squared){ + rLhs_total += rData.vol * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + } +} + +template +void CompressiblePerturbationPotentialFlowElement::CalculateRightHandSideContribution( + BoundedVector& rRhs_total, + const ProcessInfo& rCurrentProcessInfo, + const array_1d& rVelocity, + const ElementalData& rData) +{ + // Compute density + const double local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(rVelocity, rCurrentProcessInfo); + const double density = PotentialFlowUtilities::ComputeDensity(local_mach_number_squared, rCurrentProcessInfo); + + rRhs_total = - rData.vol * density * prod(rData.DN_DX, rVelocity); +} + template void CompressiblePerturbationPotentialFlowElement::CalculateLeftHandSideSubdividedElement( Matrix& lhs_positive, @@ -589,34 +619,46 @@ void CompressiblePerturbationPotentialFlowElement::CalculateLeftH Points, data.DN_DX, data.distances, Volumes, GPShapeFunctionValues, PartitionsSign, GradientsValue, NEnriched); - const double density = ComputeDensity(rCurrentProcessInfo); - const double DrhoDu2 = ComputeDensityDerivative(density, rCurrentProcessInfo); + // Compute upper and lower velocities + const array_1d& upper_velocity = PotentialFlowUtilities::ComputePerturbedVelocity(*this, rCurrentProcessInfo); + const array_1d& lower_velocity = PotentialFlowUtilities::ComputePerturbedVelocityLowerElement(*this, rCurrentProcessInfo); - // Computing local velocity - const array_1d free_stream_velocity = rCurrentProcessInfo[FREE_STREAM_VELOCITY]; - array_1d velocity = PotentialFlowUtilities::ComputeVelocity(*this); - for (unsigned int i = 0; i < Dim; i++){ - velocity[i] += free_stream_velocity[i]; - } + // Compute upper and lower densities + const double upper_local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(upper_velocity, rCurrentProcessInfo); + const double upper_density = PotentialFlowUtilities::ComputeDensity(upper_local_mach_number_squared, rCurrentProcessInfo); + + const double lower_local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(lower_velocity, rCurrentProcessInfo); + const double lower_density = PotentialFlowUtilities::ComputeDensity(lower_local_mach_number_squared, rCurrentProcessInfo); + + // Compute upper and lower density derivatives + const double upper_DrhoDu2 = PotentialFlowUtilities::ComputeDensityDerivativeWRTVelocitySquared(upper_local_mach_number_squared, rCurrentProcessInfo); + const double lower_DrhoDu2 = PotentialFlowUtilities::ComputeDensityDerivativeWRTVelocitySquared(lower_local_mach_number_squared, rCurrentProcessInfo); - const BoundedVector DNV = prod(data.DN_DX, velocity); + // Compute upper and lower lhs + const BoundedVector upper_DNV = prod(data.DN_DX, upper_velocity); + const BoundedVector lower_DNV = prod(data.DN_DX, lower_velocity); + + const double upper_local_velocity_squared = inner_prod(upper_velocity, upper_velocity); + const double lower_local_velocity_squared = inner_prod(lower_velocity, lower_velocity); + const double max_velocity_squared = PotentialFlowUtilities::ComputeMaximumVelocitySquared(rCurrentProcessInfo); // Compute the lhs and rhs that would correspond to it being divided for (unsigned int i = 0; i < nsubdivisions; ++i) { if (PartitionsSign[i] > 0) { - noalias(lhs_positive) += - Volumes[i] * density * prod(data.DN_DX, trans(data.DN_DX)); - noalias(lhs_positive) += - Volumes[i] * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + noalias(lhs_positive) += Volumes[i] * upper_density * prod(data.DN_DX, trans(data.DN_DX)); + if( upper_local_velocity_squared < max_velocity_squared){ + noalias(lhs_positive) += Volumes[i] * 2 * upper_DrhoDu2 * outer_prod(upper_DNV, trans(upper_DNV)); + } + } else { - noalias(lhs_negative) += - Volumes[i] * density * prod(data.DN_DX, trans(data.DN_DX)); - noalias(lhs_negative) += - Volumes[i] * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + noalias(lhs_negative) += Volumes[i] * lower_density * prod(data.DN_DX, trans(data.DN_DX)); + if( lower_local_velocity_squared < max_velocity_squared){ + noalias(lhs_negative) += Volumes[i] * 2 * lower_DrhoDu2 * outer_prod(lower_DNV, trans(lower_DNV)); + } } } } @@ -681,7 +723,9 @@ void CompressiblePerturbationPotentialFlowElement::AssignLeftHand Matrix& rLeftHandSideMatrix, Matrix& lhs_positive, Matrix& lhs_negative, - const BoundedMatrix& lhs_total, + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, const ElementalData& data) const { const auto& r_geometry = this->GetGeometry(); @@ -696,7 +740,7 @@ void CompressiblePerturbationPotentialFlowElement::AssignLeftHand } } else{ - AssignLeftHandSideWakeNode(rLeftHandSideMatrix, lhs_total, data, i); + AssignLeftHandSideWakeNode(rLeftHandSideMatrix, rUpper_lhs_total, rLower_lhs_total, rLhs_wake_condition, data, i); } } } @@ -704,34 +748,44 @@ void CompressiblePerturbationPotentialFlowElement::AssignLeftHand template void CompressiblePerturbationPotentialFlowElement::AssignLeftHandSideWakeElement( MatrixType& rLeftHandSideMatrix, - const BoundedMatrix& lhs_total, - const ElementalData& data) const + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& rData) const { - for (unsigned int row = 0; row < NumNodes; ++row) - AssignLeftHandSideWakeNode(rLeftHandSideMatrix, lhs_total, data, row); + for (unsigned int row = 0; row < NumNodes; ++row){ + AssignLeftHandSideWakeNode(rLeftHandSideMatrix, rUpper_lhs_total, rLower_lhs_total, rLhs_wake_condition, rData, row); + } } template void CompressiblePerturbationPotentialFlowElement::AssignLeftHandSideWakeNode( MatrixType& rLeftHandSideMatrix, - const BoundedMatrix& lhs_total, - const ElementalData& data, - unsigned int& row) const + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& rData, + unsigned int row) const { - // Filling the diagonal blocks (i.e. decoupling upper and lower dofs) - for (unsigned int column = 0; column < NumNodes; ++column) - { - rLeftHandSideMatrix(row, column) = lhs_total(row, column); - rLeftHandSideMatrix(row + NumNodes, column + NumNodes) = lhs_total(row, column); - } - // Applying wake condition on the AUXILIARY_VELOCITY_POTENTIAL dofs - if (data.distances[row] < 0.0) - for (unsigned int column = 0; column < NumNodes; ++column) - rLeftHandSideMatrix(row, column + NumNodes) = -lhs_total(row, column); // Side 1 - else if (data.distances[row] > 0.0) - for (unsigned int column = 0; column < NumNodes; ++column) - rLeftHandSideMatrix(row + NumNodes, column) = -lhs_total(row, column); // Side 2 + if (rData.distances[row] < 0.0){ + for (unsigned int column = 0; column < NumNodes; ++column){ + // Conservation of mass + rLeftHandSideMatrix(row + NumNodes, column + NumNodes) = rLower_lhs_total(row, column); + // Wake condition + rLeftHandSideMatrix(row, column) = rLhs_wake_condition(row, column); // Diagonal + rLeftHandSideMatrix(row, column + NumNodes) = -rLhs_wake_condition(row, column); // Off diagonal + } + } + else{ // else if (data.distances[row] > 0.0) + for (unsigned int column = 0; column < NumNodes; ++column){ + // Conservation of mass + rLeftHandSideMatrix(row, column) = rUpper_lhs_total(row, column); + // Wake condition + rLeftHandSideMatrix(row + NumNodes, column + NumNodes) = rLhs_wake_condition(row, column); // Diagonal + rLeftHandSideMatrix(row + NumNodes, column) = -rLhs_wake_condition(row, column); // Off diagonal + } + } } template @@ -762,77 +816,28 @@ void CompressiblePerturbationPotentialFlowElement::ComputePotenti array_1d distances; GetWakeDistances(distances); + auto& r_geometry = GetGeometry(); for (unsigned int i = 0; i < NumNodes; i++) { - double aux_potential = - GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL); - double potential = GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL); + double aux_potential = r_geometry[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL); + double potential = r_geometry[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL); double potential_jump = aux_potential - potential; if (distances[i] > 0) { - GetGeometry()[i].SetValue(POTENTIAL_JUMP, - -2.0 / vinfinity_norm * (potential_jump)); + r_geometry[i].SetLock(); + r_geometry[i].SetValue(POTENTIAL_JUMP, -2.0 / vinfinity_norm * (potential_jump)); + r_geometry[i].UnSetLock(); } else { - GetGeometry()[i].SetValue(POTENTIAL_JUMP, 2.0 / vinfinity_norm * (potential_jump)); + r_geometry[i].SetLock(); + r_geometry[i].SetValue(POTENTIAL_JUMP, 2.0 / vinfinity_norm * (potential_jump)); + r_geometry[i].UnSetLock(); } } } -template -double CompressiblePerturbationPotentialFlowElement::ComputeDensity(const ProcessInfo& rCurrentProcessInfo) const -{ - // Reading free stream conditions - const double rho_inf = rCurrentProcessInfo[FREE_STREAM_DENSITY]; - const double M_inf = rCurrentProcessInfo[FREE_STREAM_MACH]; - const double heat_capacity_ratio = rCurrentProcessInfo[HEAT_CAPACITY_RATIO]; - const double mach_number_limit = rCurrentProcessInfo[MACH_LIMIT]; - - // Computing local mach number - double local_mach_number = PotentialFlowUtilities::ComputePerturbationLocalMachNumber(*this, rCurrentProcessInfo); - - if (local_mach_number > mach_number_limit) - { // Clamping the mach number to mach_number_limit - KRATOS_WARNING("ComputeDensity") << "Clamping the local mach number to " << mach_number_limit << std::endl; - local_mach_number = mach_number_limit; - } - - // Computing squares - const double M_inf_2 = M_inf * M_inf; - const double M_2 = local_mach_number * local_mach_number; - - // Computing density according to Equation 8.9 of Drela, M. (2014) Flight Vehicle - // Aerodynamics, The MIT Press, London - const double numerator = 1 + (heat_capacity_ratio - 1) * M_inf_2 / 2; - const double denominator = 1 + (heat_capacity_ratio - 1) * M_2 / 2; - const double base = numerator / denominator; - - if (base > 0.0) - { - return rho_inf * pow(base, 1 / (heat_capacity_ratio - 1)); - } - else - { - KRATOS_WARNING("ComputeDensity") << "Using density correction" << std::endl; - return rho_inf * 0.00001; - } -} - -template -double CompressiblePerturbationPotentialFlowElement::ComputeDensityDerivative( - const double rho, const ProcessInfo& rCurrentProcessInfo) const -{ - // Reading free stream conditions - const double rho_inf = rCurrentProcessInfo[FREE_STREAM_DENSITY]; - const double heat_capacity_ratio = rCurrentProcessInfo[HEAT_CAPACITY_RATIO]; - const double a_inf = rCurrentProcessInfo[SOUND_VELOCITY]; - - return -pow(rho_inf, heat_capacity_ratio - 1) * - pow(rho, 2 - heat_capacity_ratio) / (2 * a_inf * a_inf); -} - // serializer template diff --git a/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_perturbation_potential_flow_element.h b/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_perturbation_potential_flow_element.h index 0c42245af642..fa87566fc5e7 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_perturbation_potential_flow_element.h +++ b/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_perturbation_potential_flow_element.h @@ -204,11 +204,6 @@ class CompressiblePerturbationPotentialFlowElement : public Element ///@} protected: - double ComputeDensity(const ProcessInfo& rCurrentProcessInfo) const; - - double ComputeDensityDerivative(const double density, - const ProcessInfo& rCurrentProcessInfo) const; - private: ///@name Private Operators ///@{ @@ -239,6 +234,16 @@ class CompressiblePerturbationPotentialFlowElement : public Element void CalculateRightHandSideWakeElement(VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo); + void CalculateLeftHandSideContribution(BoundedMatrix& rLhs_total, + const ProcessInfo& rCurrentProcessInfo, + const array_1d& rVelocity, + const ElementalData& rData); + + void CalculateRightHandSideContribution(BoundedVector& rRhs_total, + const ProcessInfo& rCurrentProcessInfo, + const array_1d& rVelocity, + const ElementalData& rData); + void CalculateLeftHandSideSubdividedElement(Matrix& lhs_positive, Matrix& lhs_negative, const ProcessInfo& rCurrentProcessInfo); @@ -253,17 +258,23 @@ class CompressiblePerturbationPotentialFlowElement : public Element void AssignLeftHandSideSubdividedElement(Matrix& rLeftHandSideMatrix, Matrix& lhs_positive, Matrix& lhs_negative, - const BoundedMatrix& lhs_total, + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, const ElementalData& data) const; void AssignLeftHandSideWakeElement(MatrixType& rLeftHandSideMatrix, - const BoundedMatrix& lhs_total, - const ElementalData& data) const; + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& rData) const; void AssignLeftHandSideWakeNode(MatrixType& rLeftHandSideMatrix, - const BoundedMatrix& lhs_total, - const ElementalData& data, - unsigned int& row) const; + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& rData, + unsigned int row) const; void AssignRightHandSideWakeNode(VectorType& rRightHandSideVector, const BoundedVector& rUpper_rhs, diff --git a/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_potential_flow_element.cpp b/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_potential_flow_element.cpp index dfd226e2a255..b4d787581078 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_potential_flow_element.cpp +++ b/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_potential_flow_element.cpp @@ -55,33 +55,34 @@ template void CompressiblePotentialFlowElement::CalculateLocalSystem( MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo) { - const CompressiblePotentialFlowElement& r_this = *this; - const int wake = r_this.GetValue(WAKE); - - if (wake == 0) // Normal element (non-wake) - eventually an embedded - CalculateLocalSystemNormalElement( - rLeftHandSideMatrix, rRightHandSideVector, rCurrentProcessInfo); - else // Wake element - CalculateLocalSystemWakeElement( - rLeftHandSideMatrix, rRightHandSideVector, rCurrentProcessInfo); + CalculateRightHandSide(rRightHandSideVector,rCurrentProcessInfo); + CalculateLeftHandSide(rLeftHandSideMatrix,rCurrentProcessInfo); } template void CompressiblePotentialFlowElement::CalculateRightHandSide( VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo) { - // TODO: improve speed - Matrix tmp; - CalculateLocalSystem(tmp, rRightHandSideVector, rCurrentProcessInfo); + const CompressiblePotentialFlowElement& r_this = *this; + const int wake = r_this.GetValue(WAKE); + + if (wake == 0) // Normal element (non-wake) - eventually an embedded + CalculateRightHandSideNormalElement(rRightHandSideVector, rCurrentProcessInfo); + else // Wake element + CalculateRightHandSideWakeElement(rRightHandSideVector, rCurrentProcessInfo); } template void CompressiblePotentialFlowElement::CalculateLeftHandSide( MatrixType& rLeftHandSideMatrix, const ProcessInfo& rCurrentProcessInfo) { - // TODO: improve speed - VectorType tmp; - CalculateLocalSystem(rLeftHandSideMatrix, tmp, rCurrentProcessInfo); + const CompressiblePotentialFlowElement& r_this = *this; + const int wake = r_this.GetValue(WAKE); + + if (wake == 0) // Normal element (non-wake) - eventually an embedded + CalculateLeftHandSideNormalElement(rLeftHandSideMatrix, rCurrentProcessInfo); + else // Wake element + CalculateLeftHandSideWakeElement(rLeftHandSideMatrix, rCurrentProcessInfo); } template @@ -200,15 +201,27 @@ void CompressiblePotentialFlowElement::CalculateOnIntegrationPoin } else if (rVariable == DENSITY) { - rValues[0] = ComputeDensity(rCurrentProcessInfo); + const array_1d& velocity = PotentialFlowUtilities::ComputeVelocity(*this); + + const double local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(velocity, rCurrentProcessInfo); + + rValues[0] = PotentialFlowUtilities::ComputeDensity(local_mach_number_squared, rCurrentProcessInfo); } else if (rVariable == MACH) { - rValues[0] = PotentialFlowUtilities::ComputeLocalMachNumber(*this, rCurrentProcessInfo); + const array_1d& velocity = PotentialFlowUtilities::ComputeVelocity(*this); + + const double local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(velocity, rCurrentProcessInfo); + + rValues[0] = std::sqrt(local_mach_number_squared); } else if (rVariable == SOUND_VELOCITY) { - rValues[0] = PotentialFlowUtilities::ComputeLocalSpeedOfSound(*this, rCurrentProcessInfo); + const array_1d& velocity = PotentialFlowUtilities::ComputeVelocity(*this); + + const double local_speed_of_sound_squared = PotentialFlowUtilities::ComputeLocalSpeedofSoundSquared(velocity, rCurrentProcessInfo); + + rValues[0] = std::sqrt(local_speed_of_sound_squared); } else if (rVariable == WAKE) { @@ -396,13 +409,11 @@ void CompressiblePotentialFlowElement::GetDofListWakeElement(Dofs } template -void CompressiblePotentialFlowElement::CalculateLocalSystemNormalElement( - MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo) +void CompressiblePotentialFlowElement::CalculateLeftHandSideNormalElement( + MatrixType& rLeftHandSideMatrix, const ProcessInfo& rCurrentProcessInfo) { if (rLeftHandSideMatrix.size1() != NumNodes || rLeftHandSideMatrix.size2() != NumNodes) rLeftHandSideMatrix.resize(NumNodes, NumNodes, false); - if (rRightHandSideVector.size() != NumNodes) - rRightHandSideVector.resize(NumNodes, false); rLeftHandSideMatrix.clear(); ElementalData data; @@ -410,39 +421,47 @@ void CompressiblePotentialFlowElement::CalculateLocalSystemNormal // Calculate shape functions GeometryUtils::CalculateGeometryData(GetGeometry(), data.DN_DX, data.N, data.vol); - const double density = ComputeDensity(rCurrentProcessInfo); - const double DrhoDu2 = ComputeDensityDerivative(density, rCurrentProcessInfo); + const array_1d& velocity = PotentialFlowUtilities::ComputeVelocity(*this); - // Computing local velocity - array_1d v = PotentialFlowUtilities::ComputeVelocity (*this); + BoundedMatrix lhs = ZeroMatrix(NumNodes,NumNodes); - const BoundedVector DNV = prod(data.DN_DX, v); + CalculateLeftHandSideContribution(lhs, rCurrentProcessInfo, velocity, data); - noalias(rLeftHandSideMatrix) += - data.vol * density * prod(data.DN_DX, trans(data.DN_DX)); - noalias(rLeftHandSideMatrix) += data.vol * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + noalias(rLeftHandSideMatrix) = lhs; +} - const BoundedMatrix rLaplacianMatrix = - data.vol * density * prod(data.DN_DX, trans(data.DN_DX)); +template +void CompressiblePotentialFlowElement::CalculateRightHandSideNormalElement( + VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo) +{ + if (rRightHandSideVector.size() != NumNodes) + rRightHandSideVector.resize(NumNodes, false); + rRightHandSideVector.clear(); + + ElementalData data; - data.potentials= PotentialFlowUtilities::GetPotentialOnNormalElement(*this); - noalias(rRightHandSideVector) = -prod(rLaplacianMatrix, data.potentials); + // Calculate shape functions + GeometryUtils::CalculateGeometryData(GetGeometry(), data.DN_DX, data.N, data.vol); + + const CompressiblePotentialFlowElement& r_this = *this; + + const array_1d& velocity = PotentialFlowUtilities::ComputeVelocity(r_this); + + BoundedVector rhs = ZeroVector(NumNodes); + CalculateRightHandSideContribution(rhs, rCurrentProcessInfo, velocity, data); + + noalias(rRightHandSideVector) = rhs; } template -void CompressiblePotentialFlowElement::CalculateLocalSystemWakeElement( - MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo) +void CompressiblePotentialFlowElement::CalculateLeftHandSideWakeElement( + MatrixType& rLeftHandSideMatrix, const ProcessInfo& rCurrentProcessInfo) { // Note that the lhs and rhs have double the size if (rLeftHandSideMatrix.size1() != 2 * NumNodes || rLeftHandSideMatrix.size2() != 2 * NumNodes) rLeftHandSideMatrix.resize(2 * NumNodes, 2 * NumNodes, false); - if (rRightHandSideVector.size() != 2 * NumNodes) - rRightHandSideVector.resize(2 * NumNodes, false); rLeftHandSideMatrix.clear(); - rRightHandSideVector.clear(); - - MatrixType rLaplacianMatrix = ZeroMatrix(2 * NumNodes, 2 * NumNodes); ElementalData data; @@ -450,52 +469,134 @@ void CompressiblePotentialFlowElement::CalculateLocalSystemWakeEl GeometryUtils::CalculateGeometryData(GetGeometry(), data.DN_DX, data.N, data.vol); GetWakeDistances(data.distances); - const double density = ComputeDensity(rCurrentProcessInfo); - const double DrhoDu2 = ComputeDensityDerivative(density, rCurrentProcessInfo); - - // Computing local velocity - array_1d v = PotentialFlowUtilities::ComputeVelocityUpperWakeElement(*this); + // Compute upper and lower velocities + const array_1d& upper_velocity = PotentialFlowUtilities::ComputeVelocityUpperWakeElement(*this); + const array_1d& lower_velocity = PotentialFlowUtilities::ComputeVelocityLowerWakeElement(*this); - const BoundedVector DNV = prod(data.DN_DX, v); + BoundedMatrix upper_lhs_total = ZeroMatrix(NumNodes,NumNodes); + BoundedMatrix lower_lhs_total = ZeroMatrix(NumNodes,NumNodes); - const BoundedMatrix laplacian_total = - data.vol * density * prod(data.DN_DX, trans(data.DN_DX)); + CalculateLeftHandSideContribution(upper_lhs_total, rCurrentProcessInfo, upper_velocity, data); + CalculateLeftHandSideContribution(lower_lhs_total, rCurrentProcessInfo, lower_velocity, data); - const BoundedMatrix lhs_total = - data.vol * density * prod(data.DN_DX, trans(data.DN_DX)) + - data.vol * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + // Compute lhs wake condition + const double free_stream_density = rCurrentProcessInfo[FREE_STREAM_DENSITY]; + const BoundedMatrix lhs_wake_condition = data.vol * free_stream_density * prod(data.DN_DX, trans(data.DN_DX)); if (this->Is(STRUCTURE)) { Matrix lhs_positive = ZeroMatrix(NumNodes, NumNodes); Matrix lhs_negative = ZeroMatrix(NumNodes, NumNodes); - Matrix laplacian_positive = ZeroMatrix(NumNodes, NumNodes); - Matrix laplacian_negative = ZeroMatrix(NumNodes, NumNodes); - - CalculateLocalSystemSubdividedElement(lhs_positive, lhs_negative, laplacian_positive, - laplacian_negative, rCurrentProcessInfo); - AssignLocalSystemSubdividedElement( - rLeftHandSideMatrix, lhs_positive, lhs_negative, lhs_total, rLaplacianMatrix, - laplacian_positive, laplacian_negative, laplacian_total, data); + CalculateLeftHandSideSubdividedElement(lhs_positive, lhs_negative, rCurrentProcessInfo); + AssignLeftHandSideSubdividedElement(rLeftHandSideMatrix, lhs_positive, + lhs_negative, upper_lhs_total, lower_lhs_total, lhs_wake_condition, data); } else { - AssignLocalSystemWakeElement(rLeftHandSideMatrix, lhs_total, data); - AssignLocalSystemWakeElement(rLaplacianMatrix, laplacian_total, data); + AssignLeftHandSideWakeElement(rLeftHandSideMatrix, upper_lhs_total, lower_lhs_total, lhs_wake_condition, data); } +} + +template +void CompressiblePotentialFlowElement::CalculateRightHandSideWakeElement( + VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo) +{ + // Note that the rhs has double the size + if (rRightHandSideVector.size() != 2 * NumNodes) + rRightHandSideVector.resize(2 * NumNodes, false); + rRightHandSideVector.clear(); - Vector split_element_values(2 * NumNodes); - split_element_values = PotentialFlowUtilities::GetPotentialOnWakeElement(*this, data.distances); - noalias(rRightHandSideVector) = -prod(rLaplacianMatrix, split_element_values); + ElementalData data; + + // Calculate shape functions + const auto& r_geometry = this->GetGeometry(); + GeometryUtils::CalculateGeometryData(r_geometry, data.DN_DX, data.N, data.vol); + GetWakeDistances(data.distances); + + // Compute upper and lower velocities + const array_1d& upper_velocity = PotentialFlowUtilities::ComputeVelocityUpperWakeElement(*this); + const array_1d& lower_velocity = PotentialFlowUtilities::ComputeVelocityLowerWakeElement(*this); + + // Compute upper and lower rhs + BoundedVector upper_rhs = ZeroVector(NumNodes); + BoundedVector lower_rhs = ZeroVector(NumNodes); + CalculateRightHandSideContribution(upper_rhs, rCurrentProcessInfo, upper_velocity, data); + CalculateRightHandSideContribution(lower_rhs, rCurrentProcessInfo, lower_velocity, data); + + const array_1d& diff_velocity = upper_velocity - lower_velocity; + + // Compute wake condition rhs + const double free_stream_density = rCurrentProcessInfo[FREE_STREAM_DENSITY]; + const BoundedVector wake_rhs = - data.vol * free_stream_density * prod(data.DN_DX, diff_velocity); + + if (this->Is(STRUCTURE)){ + double upper_vol = 0.0; + double lower_vol = 0.0; + + CalculateVolumesSubdividedElement(upper_vol, lower_vol, rCurrentProcessInfo); + for (unsigned int i = 0; i < NumNodes; ++i){ + if (r_geometry[i].GetValue(TRAILING_EDGE)){ + rRightHandSideVector[i] = upper_rhs(i)*upper_vol/data.vol; + rRightHandSideVector[i + NumNodes] = lower_rhs(i)*lower_vol/data.vol; + } + else{ + AssignRightHandSideWakeNode(rRightHandSideVector, upper_rhs, lower_rhs, wake_rhs, data, i); + } + } + } + else{ + for (unsigned int i = 0; i < NumNodes; ++i){ + AssignRightHandSideWakeNode(rRightHandSideVector, upper_rhs, lower_rhs, wake_rhs, data, i); + } + } } template -void CompressiblePotentialFlowElement::CalculateLocalSystemSubdividedElement( +void CompressiblePotentialFlowElement::CalculateLeftHandSideContribution( + BoundedMatrix& rLhs_total, + const ProcessInfo& rCurrentProcessInfo, + const array_1d& rVelocity, + const ElementalData& rData) +{ + // Compute density + const double local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(rVelocity, rCurrentProcessInfo); + const double density = PotentialFlowUtilities::ComputeDensity(local_mach_number_squared, rCurrentProcessInfo); + + // Compute density derivative + const double DrhoDu2 = PotentialFlowUtilities::ComputeDensityDerivativeWRTVelocitySquared(local_mach_number_squared, rCurrentProcessInfo); + + // Compute lhs + const BoundedVector DNV = prod(rData.DN_DX, rVelocity); + + rLhs_total = rData.vol * density * prod(rData.DN_DX, trans(rData.DN_DX)); + + const double local_velocity_squared = inner_prod(rVelocity, rVelocity); + + const double max_velocity_squared = PotentialFlowUtilities::ComputeMaximumVelocitySquared(rCurrentProcessInfo); + if (local_velocity_squared < max_velocity_squared){ + rLhs_total += rData.vol * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + } +} + +template +void CompressiblePotentialFlowElement::CalculateRightHandSideContribution( + BoundedVector& rRhs_total, + const ProcessInfo& rCurrentProcessInfo, + const array_1d& rVelocity, + const ElementalData& rData) +{ + // Compute density + const double local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(rVelocity, rCurrentProcessInfo); + const double density = PotentialFlowUtilities::ComputeDensity(local_mach_number_squared, rCurrentProcessInfo); + + rRhs_total = - rData.vol * density * prod(rData.DN_DX, rVelocity); +} + +template +void CompressiblePotentialFlowElement::CalculateLeftHandSideSubdividedElement( Matrix& lhs_positive, Matrix& lhs_negative, - Matrix& laplacian_positive, - Matrix& laplacian_negative, const ProcessInfo& rCurrentProcessInfo) { ElementalData data; @@ -528,36 +629,94 @@ void CompressiblePotentialFlowElement::CalculateLocalSystemSubdiv Points, data.DN_DX, data.distances, Volumes, GPShapeFunctionValues, PartitionsSign, GradientsValue, NEnriched); - const double density = ComputeDensity(rCurrentProcessInfo); - const double DrhoDu2 = ComputeDensityDerivative(density, rCurrentProcessInfo); + // Compute upper and lower velocities + const array_1d& upper_velocity = PotentialFlowUtilities::ComputeVelocityUpperWakeElement(*this); + const array_1d& lower_velocity = PotentialFlowUtilities::ComputeVelocityLowerWakeElement(*this); + + // Compute upper and lower densities + const double upper_local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(upper_velocity, rCurrentProcessInfo); + const double upper_density = PotentialFlowUtilities::ComputeDensity(upper_local_mach_number_squared, rCurrentProcessInfo); + + const double lower_local_mach_number_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared(lower_velocity, rCurrentProcessInfo); + const double lower_density = PotentialFlowUtilities::ComputeDensity(lower_local_mach_number_squared, rCurrentProcessInfo); - // Computing local velocity - array_1d v = PotentialFlowUtilities::ComputeVelocityUpperWakeElement(*this); + // Compute upper and lower density derivatives + const double upper_DrhoDu2 = PotentialFlowUtilities::ComputeDensityDerivativeWRTVelocitySquared(upper_local_mach_number_squared, rCurrentProcessInfo); + const double lower_DrhoDu2 = PotentialFlowUtilities::ComputeDensityDerivativeWRTVelocitySquared(lower_local_mach_number_squared, rCurrentProcessInfo); - const BoundedVector DNV = prod(data.DN_DX, v); + // Compute upper and lower lhs + const BoundedVector upper_DNV = prod(data.DN_DX, upper_velocity); + const BoundedVector lower_DNV = prod(data.DN_DX, lower_velocity); + + const double upper_local_velocity_squared = inner_prod(upper_velocity, upper_velocity); + const double lower_local_velocity_squared = inner_prod(lower_velocity, lower_velocity); + const double max_velocity_squared = PotentialFlowUtilities::ComputeMaximumVelocitySquared(rCurrentProcessInfo); // Compute the lhs and rhs that would correspond to it being divided for (unsigned int i = 0; i < nsubdivisions; ++i) { if (PartitionsSign[i] > 0) { - noalias(lhs_positive) += - Volumes[i] * density * prod(data.DN_DX, trans(data.DN_DX)); - noalias(lhs_positive) += - Volumes[i] * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + noalias(lhs_positive) += Volumes[i] * upper_density * prod(data.DN_DX, trans(data.DN_DX)); + if( upper_local_velocity_squared < max_velocity_squared){ + noalias(lhs_positive) += Volumes[i] * 2 * upper_DrhoDu2 * outer_prod(upper_DNV, trans(upper_DNV)); + } - noalias(laplacian_positive) += - Volumes[i] * density * prod(data.DN_DX, trans(data.DN_DX)); } else { - noalias(lhs_negative) += - Volumes[i] * density * prod(data.DN_DX, trans(data.DN_DX)); - noalias(lhs_negative) += - Volumes[i] * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + noalias(lhs_negative) += Volumes[i] * lower_density * prod(data.DN_DX, trans(data.DN_DX)); + if( lower_local_velocity_squared < max_velocity_squared){ + noalias(lhs_negative) += Volumes[i] * 2 * lower_DrhoDu2 * outer_prod(lower_DNV, trans(lower_DNV)); + } + } + } +} + +template +void CompressiblePotentialFlowElement::CalculateVolumesSubdividedElement( + double& rUpper_vol, + double& rLower_vol, + const ProcessInfo& rCurrentProcessInfo) +{ + ElementalData data; + + // Calculate shape functions + GeometryUtils::CalculateGeometryData(GetGeometry(), data.DN_DX, data.N, data.vol); + + GetWakeDistances(data.distances); + + // Subdivide the element + constexpr unsigned int nvolumes = 3 * (Dim - 1); + BoundedMatrix Points; + array_1d PartitionsSign; + BoundedMatrix GPShapeFunctionValues; + array_1d Volumes; + std::vector GradientsValue(nvolumes); + BoundedMatrix NEnriched; + for (unsigned int i = 0; i < GradientsValue.size(); ++i) + GradientsValue[i].resize(2, Dim, false); + for (unsigned int i = 0; i < NumNodes; ++i) + { + const array_1d& coords = GetGeometry()[i].Coordinates(); + for (unsigned int k = 0; k < Dim; ++k) + { + Points(i, k) = coords[k]; + } + } - noalias(laplacian_negative) += - Volumes[i] * density * prod(data.DN_DX, trans(data.DN_DX)); + const unsigned int nsubdivisions = EnrichmentUtilities::CalculateEnrichedShapeFuncions( + Points, data.DN_DX, data.distances, Volumes, GPShapeFunctionValues, + PartitionsSign, GradientsValue, NEnriched); + + // Compute the volumes that would correspond to it being divided + for (unsigned int i = 0; i < nsubdivisions; ++i) + { + if (PartitionsSign[i] > 0){ + rUpper_vol += Volumes[i]; + } + else{ + rLower_vol += Volumes[i]; } } } @@ -570,71 +729,92 @@ void CompressiblePotentialFlowElement::ComputeLHSGaussPointContri } template -void CompressiblePotentialFlowElement::AssignLocalSystemSubdividedElement( +void CompressiblePotentialFlowElement::AssignLeftHandSideSubdividedElement( Matrix& rLeftHandSideMatrix, Matrix& lhs_positive, Matrix& lhs_negative, - const BoundedMatrix& lhs_total, - MatrixType& rLaplacianMatrix, - Matrix& laplacian_positive, - Matrix& laplacian_negative, - const BoundedMatrix& laplacian_total, + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, const ElementalData& data) const { + const auto& r_geometry = this->GetGeometry(); for (unsigned int i = 0; i < NumNodes; ++i) { // The TE node takes the contribution of the subdivided element and // we do not apply the wake condition on the TE node - if (GetGeometry()[i].GetValue(TRAILING_EDGE)) - { - for (unsigned int j = 0; j < NumNodes; ++j) - { + if (r_geometry[i].GetValue(TRAILING_EDGE)){ + for (unsigned int j = 0; j < NumNodes; ++j){ rLeftHandSideMatrix(i, j) = lhs_positive(i, j); rLeftHandSideMatrix(i + NumNodes, j + NumNodes) = lhs_negative(i, j); - - rLaplacianMatrix(i, j) = laplacian_positive(i, j); - rLaplacianMatrix(i + NumNodes, j + NumNodes) = laplacian_negative(i, j); } } - else - { - AssignLocalSystemWakeNode(rLeftHandSideMatrix, lhs_total, data, i); - AssignLocalSystemWakeNode(rLaplacianMatrix, laplacian_total, data, i); + else{ + AssignLeftHandSideWakeNode(rLeftHandSideMatrix, rUpper_lhs_total, rLower_lhs_total, rLhs_wake_condition, data, i); } } } template -void CompressiblePotentialFlowElement::AssignLocalSystemWakeElement( +void CompressiblePotentialFlowElement::AssignLeftHandSideWakeElement( MatrixType& rLeftHandSideMatrix, - const BoundedMatrix& lhs_total, - const ElementalData& data) const + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& rData) const { - for (unsigned int row = 0; row < NumNodes; ++row) - AssignLocalSystemWakeNode(rLeftHandSideMatrix, lhs_total, data, row); + for (unsigned int row = 0; row < NumNodes; ++row){ + AssignLeftHandSideWakeNode(rLeftHandSideMatrix, rUpper_lhs_total, rLower_lhs_total, rLhs_wake_condition, rData, row); + } } template -void CompressiblePotentialFlowElement::AssignLocalSystemWakeNode( +void CompressiblePotentialFlowElement::AssignLeftHandSideWakeNode( MatrixType& rLeftHandSideMatrix, - const BoundedMatrix& lhs_total, - const ElementalData& data, - unsigned int& row) const + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& rData, + unsigned int row) const { - // Filling the diagonal blocks (i.e. decoupling upper and lower dofs) - for (unsigned int column = 0; column < NumNodes; ++column) - { - rLeftHandSideMatrix(row, column) = lhs_total(row, column); - rLeftHandSideMatrix(row + NumNodes, column + NumNodes) = lhs_total(row, column); + // Applying wake condition on the AUXILIARY_VELOCITY_POTENTIAL dofs + if (rData.distances[row] < 0.0){ + for (unsigned int column = 0; column < NumNodes; ++column){ + // Conservation of mass + rLeftHandSideMatrix(row + NumNodes, column + NumNodes) = rLower_lhs_total(row, column); + // Wake condition + rLeftHandSideMatrix(row, column) = rLhs_wake_condition(row, column); // Diagonal + rLeftHandSideMatrix(row, column + NumNodes) = -rLhs_wake_condition(row, column); // Off diagonal + } + } + else{ // else if (data.distances[row] > 0.0) + for (unsigned int column = 0; column < NumNodes; ++column){ + // Conservation of mass + rLeftHandSideMatrix(row, column) = rUpper_lhs_total(row, column); + // Wake condition + rLeftHandSideMatrix(row + NumNodes, column + NumNodes) = rLhs_wake_condition(row, column); // Diagonal + rLeftHandSideMatrix(row + NumNodes, column) = -rLhs_wake_condition(row, column); // Off diagonal + } } +} - // Applying wake condition on the AUXILIARY_VELOCITY_POTENTIAL dofs - if (data.distances[row] < 0.0) - for (unsigned int column = 0; column < NumNodes; ++column) - rLeftHandSideMatrix(row, column + NumNodes) = -lhs_total(row, column); // Side 1 - else if (data.distances[row] > 0.0) - for (unsigned int column = 0; column < NumNodes; ++column) - rLeftHandSideMatrix(row + NumNodes, column) = -lhs_total(row, column); // Side 2 +template +void CompressiblePotentialFlowElement::AssignRightHandSideWakeNode( + VectorType& rRightHandSideVector, + const BoundedVector& rUpper_rhs, + const BoundedVector& rLower_rhs, + const BoundedVector& rWake_rhs, + const ElementalData& rData, + unsigned int& rRow) const +{ + if (rData.distances[rRow] > 0.0){ + rRightHandSideVector[rRow] = rUpper_rhs(rRow); + rRightHandSideVector[rRow + NumNodes] = -rWake_rhs(rRow); + } + else{ + rRightHandSideVector[rRow] = rWake_rhs(rRow); + rRightHandSideVector[rRow + NumNodes] = rLower_rhs(rRow); + } } template @@ -646,21 +826,24 @@ void CompressiblePotentialFlowElement::ComputePotentialJump(const array_1d distances; GetWakeDistances(distances); + auto& r_geometry = GetGeometry(); for (unsigned int i = 0; i < NumNodes; i++) { - double aux_potential = - GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL); - double potential = GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL); + double aux_potential = r_geometry[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL); + double potential = r_geometry[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL); double potential_jump = aux_potential - potential; if (distances[i] > 0) { - GetGeometry()[i].SetValue(POTENTIAL_JUMP, - -2.0 / vinfinity_norm * (potential_jump)); + r_geometry[i].SetLock(); + r_geometry[i].SetValue(POTENTIAL_JUMP, -2.0 / vinfinity_norm * (potential_jump)); + r_geometry[i].UnSetLock(); } else { - GetGeometry()[i].SetValue(POTENTIAL_JUMP, 2.0 / vinfinity_norm * (potential_jump)); + r_geometry[i].SetLock(); + r_geometry[i].SetValue(POTENTIAL_JUMP, 2.0 / vinfinity_norm * (potential_jump)); + r_geometry[i].UnSetLock(); } } } diff --git a/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_potential_flow_element.h b/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_potential_flow_element.h index 20ddad10d04a..87a310c0b3a3 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_potential_flow_element.h +++ b/applications/CompressiblePotentialFlowApplication/custom_elements/compressible_potential_flow_element.h @@ -227,43 +227,67 @@ class CompressiblePotentialFlowElement : public Element void GetDofListWakeElement(DofsVectorType& rElementalDofList) const; - void CalculateLocalSystemNormalElement(MatrixType& rLeftHandSideMatrix, - VectorType& rRightHandSideVector, + void CalculateLeftHandSideNormalElement(MatrixType& rLeftHandSideMatrix, const ProcessInfo& rCurrentProcessInfo); - void CalculateLocalSystemWakeElement(MatrixType& rLeftHandSideMatrix, - VectorType& rRightHandSideVector, + void CalculateRightHandSideNormalElement(VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo); + + void CalculateLeftHandSideWakeElement(MatrixType& rLeftHandSideMatrix, + const ProcessInfo& rCurrentProcessInfo); + + void CalculateRightHandSideWakeElement(VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo); - void CalculateLocalSystemSubdividedElement(Matrix& lhs_positive, + void CalculateLeftHandSideContribution(BoundedMatrix& rLhs_total, + const ProcessInfo& rCurrentProcessInfo, + const array_1d& rVelocity, + const ElementalData& rData); + + void CalculateRightHandSideContribution(BoundedVector& rRhs_total, + const ProcessInfo& rCurrentProcessInfo, + const array_1d& rVelocity, + const ElementalData& rData); + + void CalculateLeftHandSideSubdividedElement(Matrix& lhs_positive, Matrix& lhs_negative, - Matrix& laplacian_positive, - Matrix& laplacian_negative, const ProcessInfo& rCurrentProcessInfo); + void CalculateVolumesSubdividedElement(double& rUpper_vol, + double& rLower_vol, + const ProcessInfo& rCurrentProcessInfo); + void ComputeLHSGaussPointContribution(const double weight, Matrix& lhs, const ElementalData& data) const; - void AssignLocalSystemSubdividedElement( - Matrix& rLeftHandSideMatrix, - Matrix& lhs_positive, - Matrix& lhs_negative, - const BoundedMatrix& lhs_total, - MatrixType& rLaplacianMatrix, - Matrix& laplacian_positive, - Matrix& laplacian_negative, - const BoundedMatrix& laplacian_total, - const ElementalData& data) const; - - void AssignLocalSystemWakeElement(MatrixType& rLeftHandSideMatrix, - const BoundedMatrix& lhs_total, - const ElementalData& data) const; - - void AssignLocalSystemWakeNode(MatrixType& rLeftHandSideMatrix, - const BoundedMatrix& lhs_total, - const ElementalData& data, - unsigned int& row) const; + void AssignLeftHandSideSubdividedElement(Matrix& rLeftHandSideMatrix, + Matrix& lhs_positive, + Matrix& lhs_negative, + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& data) const; + + void AssignLeftHandSideWakeElement(MatrixType& rLeftHandSideMatrix, + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& rData) const; + + void AssignLeftHandSideWakeNode(MatrixType& rLeftHandSideMatrix, + const BoundedMatrix& rUpper_lhs_total, + const BoundedMatrix& rLower_lhs_total, + const BoundedMatrix& rLhs_wake_condition, + const ElementalData& rData, + unsigned int row) const; + + void AssignRightHandSideWakeNode(VectorType& rRightHandSideVector, + const BoundedVector& rUpper_rhs, + const BoundedVector& rLower_rhs, + const BoundedVector& rWake_rhs, + const ElementalData& rData, + unsigned int& rRow) const; void ComputePotentialJump(const ProcessInfo& rCurrentProcessInfo); diff --git a/applications/CompressiblePotentialFlowApplication/custom_elements/embedded_compressible_potential_flow_element.cpp b/applications/CompressiblePotentialFlowApplication/custom_elements/embedded_compressible_potential_flow_element.cpp index b965afbf9707..d70ee7609777 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_elements/embedded_compressible_potential_flow_element.cpp +++ b/applications/CompressiblePotentialFlowApplication/custom_elements/embedded_compressible_potential_flow_element.cpp @@ -100,22 +100,27 @@ void EmbeddedCompressiblePotentialFlowElement::CalculateEmbeddedL GeometryData::GI_GAUSS_2); // Computing local velocity - array_1d v = PotentialFlowUtilities::ComputeVelocityNormalElement(*this); + const array_1d& local_velocity = PotentialFlowUtilities::ComputeVelocityNormalElement(*this); + const double local_velocity_squared = inner_prod(local_velocity, local_velocity); + const double max_velocity_squared = PotentialFlowUtilities::ComputeMaximumVelocitySquared(rCurrentProcessInfo); BoundedMatrix DN_DX; BoundedVector DNV; - BoundedMatrix rLaplacianMatrix; - rLaplacianMatrix.clear(); + BoundedMatrix laplacian; + laplacian.clear(); + for (unsigned int i_gauss=0;i_gauss aux_matrix = positive_side_weights(i_gauss) * density * prod(DN_DX, trans(DN_DX)); + noalias(laplacian) += aux_matrix; + noalias(rLeftHandSideMatrix) += aux_matrix; + if (local_velocity_squared < max_velocity_squared){ + noalias(rLeftHandSideMatrix) += positive_side_weights(i_gauss) * 2 * DrhoDu2 * outer_prod(DNV, trans(DNV)); + } } - noalias(rRightHandSideVector) = -prod(rLaplacianMatrix, potential); + noalias(rRightHandSideVector) = -prod(laplacian, potential); } template <> diff --git a/applications/CompressiblePotentialFlowApplication/custom_python/add_custom_utilities_to_python.cpp b/applications/CompressiblePotentialFlowApplication/custom_python/add_custom_utilities_to_python.cpp index 914ecc6e8673..21c9793cc8be 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_python/add_custom_utilities_to_python.cpp +++ b/applications/CompressiblePotentialFlowApplication/custom_python/add_custom_utilities_to_python.cpp @@ -31,6 +31,8 @@ void AddCustomUtilitiesToPython(pybind11::module& m) mod_potential_flow_utilities.def("CheckIfWakeConditionsAreFulfilled2D",&PotentialFlowUtilities::CheckIfWakeConditionsAreFulfilled<2>); mod_potential_flow_utilities.def("CheckIfWakeConditionsAreFulfilled3D",&PotentialFlowUtilities::CheckIfWakeConditionsAreFulfilled<3>); + mod_potential_flow_utilities.def("CalculateArea",&PotentialFlowUtilities::CalculateArea); + mod_potential_flow_utilities.def("CalculateArea",&PotentialFlowUtilities::CalculateArea); } } // namespace Python. diff --git a/applications/CompressiblePotentialFlowApplication/custom_python/compressible_potential_flow_python_application.cpp b/applications/CompressiblePotentialFlowApplication/custom_python/compressible_potential_flow_python_application.cpp index df5ce7c3c1a3..c04771700b26 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_python/compressible_potential_flow_python_application.cpp +++ b/applications/CompressiblePotentialFlowApplication/custom_python/compressible_potential_flow_python_application.cpp @@ -85,6 +85,8 @@ PYBIND11_MODULE(KratosCompressiblePotentialFlowApplication, m) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, CRITICAL_MACH); KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, UPWIND_FACTOR_CONSTANT); + // Settings + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, ECHO_LEVEL); // Integral magnitudes KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, LIFT_COEFFICIENT); KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, MOMENT_COEFFICIENT); diff --git a/applications/CompressiblePotentialFlowApplication/custom_utilities/potential_flow_utilities.cpp b/applications/CompressiblePotentialFlowApplication/custom_utilities/potential_flow_utilities.cpp index 3994f87bb12e..79aeaa850eb6 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_utilities/potential_flow_utilities.cpp +++ b/applications/CompressiblePotentialFlowApplication/custom_utilities/potential_flow_utilities.cpp @@ -119,7 +119,7 @@ array_1d ComputeVelocity(const Element& rElement) template array_1d ComputePerturbedVelocity( - const Element& rElement, + const Element& rElement, const ProcessInfo& rCurrentProcessInfo) { const array_1d free_stream_velocity = rCurrentProcessInfo[FREE_STREAM_VELOCITY]; @@ -132,6 +132,21 @@ array_1d ComputePerturbedVelocity( return velocity; } +template +array_1d ComputePerturbedVelocityLowerElement( + const Element& rElement, + const ProcessInfo& rCurrentProcessInfo) +{ + const array_1d free_stream_velocity = rCurrentProcessInfo[FREE_STREAM_VELOCITY]; + array_1d velocity = ComputeVelocityLowerWakeElement(rElement); + for (unsigned int i = 0; i < Dim; i++) + { + velocity[i] += free_stream_velocity[i]; + } + + return velocity; +} + template double ComputeMaximumVelocitySquared(const ProcessInfo& rCurrentProcessInfo) { @@ -165,6 +180,32 @@ double ComputeMaximumVelocitySquared(const ProcessInfo& rCurrentProcessInfo) return factor * numerator / denominator; } +double ComputeVacuumVelocitySquared(const ProcessInfo& rCurrentProcessInfo) +{ + // Following Fully Simulataneous Coupling of the Full Potential Equation + // and the Integral Boundary Layer Equations in Three Dimensions + // by Brian Nishida (1996), Section 2.5 + + // read free stream values + const double heat_capacity_ratio = rCurrentProcessInfo[HEAT_CAPACITY_RATIO]; + const double free_stream_mach = rCurrentProcessInfo[FREE_STREAM_MACH]; + KRATOS_ERROR_IF(free_stream_mach < std::numeric_limits::epsilon()) + << "ComputeVacuumVelocitySquared: free_stream_mach must be larger than zero." << std::endl; + + const array_1d& free_stream_velocity = rCurrentProcessInfo[FREE_STREAM_VELOCITY]; + + // compute squares of values + const double free_stream_mach_squared = std::pow(free_stream_mach, 2.0); + const double free_stream_velocity_squared = inner_prod(free_stream_velocity, free_stream_velocity); + + const double denominator = (heat_capacity_ratio - 1.0) * free_stream_mach_squared; + + KRATOS_ERROR_IF(denominator < std::numeric_limits::epsilon()) + << "ComputeVacuumVelocitySquared: denominatior must be larger than zero." << std::endl; + + return free_stream_velocity_squared * ( 1 + 2 / denominator); +} + // This function returns the square of the magnitude of the velocity, // clamping it if it is over the maximum allowed template @@ -179,7 +220,7 @@ double ComputeClampedVelocitySquared( // check if local velocity should be changed if (local_velocity_squared > max_velocity_squared) { - KRATOS_WARNING("Clamped local velocity") << + KRATOS_WARNING_IF("Clamped local velocity", rCurrentProcessInfo[ECHO_LEVEL] > 0) << "SQUARE OF LOCAL VELOCITY ABOVE ALLOWED SQUARE OF VELOCITY" << " local_velocity_squared = " << local_velocity_squared << " max_velocity_squared = " << max_velocity_squared << std::endl; @@ -338,15 +379,16 @@ double ComputePerturbationCompressiblePressureCoefficient(const Element& rElemen const double heat_capacity_ratio = rCurrentProcessInfo[HEAT_CAPACITY_RATIO]; // Computing local velocity - array_1d velocity = ComputeVelocity(rElement); - for (unsigned int i = 0; i < Dim; i++){ - velocity[i] += free_stream_velocity[i]; - } + const array_1d& velocity = ComputePerturbedVelocity(rElement, rCurrentProcessInfo); // Computing squares const double v_inf_2 = inner_prod(free_stream_velocity, free_stream_velocity); const double M_inf_2 = M_inf * M_inf; double v_2 = inner_prod(velocity, velocity); + const double vacuum_velocity_squared = ComputeVacuumVelocitySquared(rCurrentProcessInfo); + if( v_2 > vacuum_velocity_squared){ + v_2 = vacuum_velocity_squared; + } KRATOS_ERROR_IF(v_inf_2 < std::numeric_limits::epsilon()) << "Error on element -> " << rElement.Id() << "\n" @@ -547,7 +589,7 @@ double ComputePerturbationLocalMachNumber(const Element& rElement, const Process template double ComputeUpwindFactor( - double localMachNumberSquared, + double localMachNumberSquared, const ProcessInfo& rCurrentProcessInfo) { // Following Fully Simulataneous Coupling of the Full Potential Equation @@ -561,7 +603,8 @@ double ComputeUpwindFactor( if(localMachNumberSquared < 1e-3){ localMachNumberSquared = 1e-3; - KRATOS_WARNING("ComputeUpwindFactor") << "localMachNumberSquared is smaller than 1-3 and is being clamped to 1e-3" << std::endl; + KRATOS_WARNING_IF("ComputeUpwindFactor", rCurrentProcessInfo[ECHO_LEVEL] > 0) + << "localMachNumberSquared is smaller than 1-3 and is being clamped to 1e-3" << std::endl; } return upwind_factor_constant * (1.0 - std::pow(critical_mach, 2.0) / localMachNumberSquared); @@ -569,8 +612,8 @@ double ComputeUpwindFactor( template double SelectMaxUpwindFactor( - const array_1d& rCurrentVelocity, - const array_1d& rUpwindVelocity, + const array_1d& rCurrentVelocity, + const array_1d& rUpwindVelocity, const ProcessInfo& rCurrentProcessInfo) { // Following Fully Simulataneous Coupling of the Full Potential Equation @@ -602,7 +645,7 @@ size_t ComputeUpwindFactorCase(array_1d& rUpwindFactorOptions) rUpwindFactorOptions[2] = 0.0; } const auto max_upwind_factor_opt = std::max_element(rUpwindFactorOptions.begin(), rUpwindFactorOptions.end()); - + // Case 0: Subsonic flow // Case 1: Supersonic and accelerating flow (M^2 > M^2_up) // Case 2: Supersonic and decelerating flow (M^2 < M^2_up) @@ -647,7 +690,7 @@ double ComputeUpwindFactorDerivativeWRTVelocitySquared( template double ComputeDensity( - const double localMachNumberSquared, + const double localMachNumberSquared, const ProcessInfo& rCurrentProcessInfo) { // Implemented according to Equation 8.9 of Drela, M. (2014) Flight Vehicle @@ -673,8 +716,8 @@ double ComputeDensity( template double ComputeUpwindedDensity( - const array_1d& rCurrentVelocity, - const array_1d& rUpwindVelocity, + const array_1d& rCurrentVelocity, + const array_1d& rUpwindVelocity, const ProcessInfo& rCurrentProcessInfo) { // Following Fully Simulataneous Coupling of the Full Potential Equation @@ -694,7 +737,7 @@ double ComputeUpwindedDensity( template double ComputeDensityDerivativeWRTVelocitySquared( - const double localMachNumberSquared, + const double localMachNumberSquared, const ProcessInfo& rCurrentProcessInfo) { // Following Fully Simulataneous Coupling of the Full Potential Equation @@ -726,9 +769,9 @@ double ComputeDensityDerivativeWRTVelocitySquared( template double ComputeUpwindedDensityDerivativeWRTVelocitySquaredSupersonicAccelerating( - const array_1d& rCurrentVelocity, + const array_1d& rCurrentVelocity, const double currentMachNumberSquared, - const double upwindMachNumberSquared, + const double upwindMachNumberSquared, const ProcessInfo& rCurrentProcessInfo) { // Following Fully Simulataneous Coupling of the Full Potential Equation @@ -754,7 +797,7 @@ double ComputeUpwindedDensityDerivativeWRTVelocitySquaredSupersonicDeacceleratin { // Following Fully Simulataneous Coupling of the Full Potential Equation // and the Integral Boundary Layer Equations in Three Dimensions - // by Brian Nishida (1996), Section A.2.6 + // by Brian Nishida (1996), Section A.2.6 // const double current_mach_sq = ComputeLocalMachNumberSquared(rCurrentVelocity, rCurrentProcessInfo); const double Drho_Dq2 = ComputeDensityDerivativeWRTVelocitySquared(currentMachNumberSquared, rCurrentProcessInfo); @@ -767,7 +810,7 @@ double ComputeUpwindedDensityDerivativeWRTVelocitySquaredSupersonicDeacceleratin template double ComputeUpwindedDensityDerivativeWRTUpwindVelocitySquaredSupersonicAccelerating( const double currentMachNumberSquared, - const double upwindMachNumberSquared, + const double upwindMachNumberSquared, const ProcessInfo& rCurrentProcessInfo) { // Following Fully Simulataneous Coupling of the Full Potential Equation @@ -784,7 +827,7 @@ template double ComputeUpwindedDensityDerivativeWRTUpwindVelocitySquaredSupersonicDeaccelerating( const array_1d& rUpwindVelocity, const double currentMachNumberSquared, - const double upwindMachNumberSquared, + const double upwindMachNumberSquared, const ProcessInfo& rCurrentProcessInfo) { // Following Fully Simulataneous Coupling of the Full Potential Equation @@ -905,6 +948,16 @@ void GetNodeNeighborElementCandidates(GlobalPointersVector& ElementCand } } } + +template +double CalculateArea(TContainerType& rContainer) +{ + double area = block_for_each>(rContainer, [&](typename TContainerType::value_type& rEntity){ + return rEntity.GetGeometry().Area(); + }); + + return area; +} /////////////////////////////////////////////////////////////////////////////////////////////////// // Template instantiation @@ -922,6 +975,7 @@ template array_1d ComputeVelocityUpperWakeElement<2, 3>(const Element template array_1d ComputeVelocityLowerWakeElement<2, 3>(const Element& rElement); template array_1d ComputeVelocity<2, 3>(const Element& rElement); template array_1d ComputePerturbedVelocity<2,3>(const Element& rElement, const ProcessInfo& rCurrentProcessInfo); +template array_1d ComputePerturbedVelocityLowerElement<2,3>(const Element& rElement, const ProcessInfo& rCurrentProcessInfo); template double ComputeMaximumVelocitySquared<2, 3>(const ProcessInfo& rCurrentProcessInfo); template double ComputeClampedVelocitySquared<2, 3>(const array_1d& rVelocity, const ProcessInfo& rCurrentProcessInfo); template double ComputeVelocityMagnitude<2, 3>(const double localMachNumberSquared, const ProcessInfo& rCurrentProcessInfo); @@ -968,6 +1022,7 @@ template array_1d ComputeVelocityUpperWakeElement<3, 4>(const Element template array_1d ComputeVelocityLowerWakeElement<3, 4>(const Element& rElement); template array_1d ComputeVelocity<3, 4>(const Element& rElement); template array_1d ComputePerturbedVelocity<3,4>(const Element& rElement, const ProcessInfo& rCurrentProcessInfo); +template array_1d ComputePerturbedVelocityLowerElement<3,4>(const Element& rElement, const ProcessInfo& rCurrentProcessInfo); template double ComputeMaximumVelocitySquared<3, 4>(const ProcessInfo& rCurrentProcessInfo); template double ComputeClampedVelocitySquared<3, 4>(const array_1d& rVelocity, const ProcessInfo& rCurrentProcessInfo); template double ComputeVelocityMagnitude<3, 4>(const double localMachNumberSquared, const ProcessInfo& rCurrentProcessInfo); @@ -1000,5 +1055,7 @@ template void KRATOS_API(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION) CheckIfWakeCo template bool CheckWakeCondition<3, 4>(const Element& rElement, const double& rTolerance, const int& rEchoLevel); template void GetSortedIds<3, 4>(std::vector& Ids, const GeometryType& rGeom); template void GetNodeNeighborElementCandidates<3, 4>(GlobalPointersVector& ElementCandidates, const GeometryType& rGeom); +template double KRATOS_API(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION) CalculateArea(ModelPart::ElementsContainerType& rContainer); +template double KRATOS_API(COMPRESSIBLE_POTENTIAL_FLOW_APPLICATION) CalculateArea(ModelPart::ConditionsContainerType& rContainer); } // namespace PotentialFlow } // namespace Kratos diff --git a/applications/CompressiblePotentialFlowApplication/custom_utilities/potential_flow_utilities.h b/applications/CompressiblePotentialFlowApplication/custom_utilities/potential_flow_utilities.h index ec36f5219254..8fee578eb676 100644 --- a/applications/CompressiblePotentialFlowApplication/custom_utilities/potential_flow_utilities.h +++ b/applications/CompressiblePotentialFlowApplication/custom_utilities/potential_flow_utilities.h @@ -79,9 +79,14 @@ array_1d ComputeVelocity(const Element& rElement); template array_1d ComputePerturbedVelocity(const Element& rElement, const ProcessInfo& rCurrentProcessInfo); +template +array_1d ComputePerturbedVelocityLowerElement(const Element& rElement, const ProcessInfo& rCurrentProcessInfo); + template double ComputeMaximumVelocitySquared(const ProcessInfo& rCurrentProcessInfo); +double ComputeVacuumVelocitySquared(const ProcessInfo& rCurrentProcessInfo); + template double ComputeClampedVelocitySquared(const array_1d& rVelocity, const ProcessInfo& rCurrentProcessInfo); @@ -176,6 +181,9 @@ void GetSortedIds(std::vector& Ids, const GeometryType& rGeom); template void GetNodeNeighborElementCandidates(GlobalPointersVector& ElementCandidates, const GeometryType& rGeom); + +template +double CalculateArea(TContainerType& rContainer); } // namespace PotentialFlow } // namespace Kratos diff --git a/applications/CompressiblePotentialFlowApplication/python_scripts/define_wake_process_2d.py b/applications/CompressiblePotentialFlowApplication/python_scripts/define_wake_process_2d.py index 4b21fbea1ab7..9769123f01ee 100644 --- a/applications/CompressiblePotentialFlowApplication/python_scripts/define_wake_process_2d.py +++ b/applications/CompressiblePotentialFlowApplication/python_scripts/define_wake_process_2d.py @@ -19,6 +19,7 @@ def __init__(self, Model, settings): default_settings = KratosMultiphysics.Parameters(r'''{ "model_part_name": "", "epsilon": 1e-9, + "compute_wake_at_each_step": false, "echo_level": 1 }''') settings.ValidateAndAssignDefaults(default_settings) @@ -35,6 +36,8 @@ def __init__(self, Model, settings): self.fluid_model_part = self.body_model_part.GetRootModelPart() + self.compute_wake_at_each_step = settings["compute_wake_at_each_step"].GetBool() + for cond in self.body_model_part.Conditions: for node in cond.GetNodes(): node.Set(KratosMultiphysics.SOLID) @@ -45,6 +48,11 @@ def ExecuteInitialize(self): #self.__FindWakeElements() + def ExecuteInitializeSolutionStep(self): + + if self.compute_wake_at_each_step and self.fluid_model_part.ProcessInfo[KratosMultiphysics.STEP] > 1: + CPFApp.Define2DWakeProcess(self.body_model_part, self.epsilon).ExecuteInitialize() + def ExecuteFinalizeSolutionStep(self): if not self.fluid_model_part.HasSubModelPart("wake_sub_model_part"): raise Exception("Fluid model part does not have a wake_sub_model_part") diff --git a/applications/CompressiblePotentialFlowApplication/python_scripts/potential_flow_solver.py b/applications/CompressiblePotentialFlowApplication/python_scripts/potential_flow_solver.py index 5c8ac8044376..aa7319187284 100644 --- a/applications/CompressiblePotentialFlowApplication/python_scripts/potential_flow_solver.py +++ b/applications/CompressiblePotentialFlowApplication/python_scripts/potential_flow_solver.py @@ -190,6 +190,7 @@ def Initialize(self): solution_strategy = self._GetSolutionStrategy() solution_strategy.SetEchoLevel(self.settings["echo_level"].GetInt()) solution_strategy.Initialize() + self.GetComputingModelPart().ProcessInfo.SetValue(KCPFApp.ECHO_LEVEL, self.settings["echo_level"].GetInt()) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Solver initialization finished.") diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_compressible_perturbation_potential_element.cpp b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_compressible_perturbation_potential_element.cpp index 25f731eba8a1..1cde2f6bf488 100644 --- a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_compressible_perturbation_potential_element.cpp +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_compressible_perturbation_potential_element.cpp @@ -17,6 +17,7 @@ #include "compressible_potential_flow_application_variables.h" #include "fluid_dynamics_application_variables.h" #include "custom_elements/compressible_perturbation_potential_flow_element.h" +#include "custom_utilities/potential_flow_utilities.h" namespace Kratos { namespace Testing { @@ -35,7 +36,8 @@ void GenerateCompressiblePerturbationElement(ModelPart& rModelPart) { rModelPart.GetProcessInfo()[FREE_STREAM_MACH] = 0.6; rModelPart.GetProcessInfo()[HEAT_CAPACITY_RATIO] = 1.4; rModelPart.GetProcessInfo()[SOUND_VELOCITY] = 340.3; - rModelPart.GetProcessInfo()[MACH_LIMIT] = 0.99; + rModelPart.GetProcessInfo()[MACH_LIMIT] = 0.94; + rModelPart.GetProcessInfo()[MACH_SQUARED_LIMIT] = 0.8836; BoundedVector free_stream_velocity = ZeroVector(3); free_stream_velocity(0) = rModelPart.GetProcessInfo().GetValue(FREE_STREAM_MACH) * rModelPart.GetProcessInfo().GetValue(SOUND_VELOCITY); @@ -49,14 +51,91 @@ void GenerateCompressiblePerturbationElement(ModelPart& rModelPart) { rModelPart.CreateNewElement("CompressiblePerturbationPotentialFlowElement2D3N", 1, elemNodes, pElemProp); } -void AssignPotentialsToNormalCompressiblePerturbationElement(Element::Pointer pElement) +void AssignPotentialsToNormalCompressiblePerturbationElement(Element::Pointer pElement, const std::array rPotential) { - std::array potential{1.0, 100.0, 150.0}; - for (unsigned int i = 0; i < 3; i++) - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; + pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i]; +} + +BoundedVector AssignDistancesToPerturbationCompressibleElement() +{ + BoundedVector distances; + distances(0) = 1.0; + distances(1) = -1.0; + distances(2) = -1.0; + return distances; } +void AssignPotentialsToWakeCompressiblePerturbationElement(Element::Pointer pElement, const array_1d& rDistances, const std::array& rPotential) +{ + for (unsigned int i = 0; i < 3; i++){ + if (rDistances(i) > 0.0) + pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i]; + else + pElement->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = rPotential[i]; + } + for (unsigned int i = 0; i < 3; i++){ + if (rDistances(i) < 0.0) + pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i+3]; + else + pElement->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = rPotential[i+3]; + } +} + +void PrintTestWakeMatrixPretty(Matrix& rMatrix){ + std::cout.precision(5); + std::cout << std::scientific; + std::cout << std::showpos; + std::cout << std::endl; + for(unsigned int row = 0; row < rMatrix.size1(); ++row){ + for(unsigned int column = 0; column < rMatrix.size2(); column++){ + if(column == 2 || column == 5){ + std::cout << " " << rMatrix(row, column) << " |"; + } + else{ + std::cout << " " << rMatrix(row, column) << " "; + } + } + + std::cout << std::endl; + + if(row ==2|| row == 5){ + for(unsigned int j = 0; j < 14*rMatrix.size1(); j++){ + std::cout << "_" ; + } + std::cout << " " << std::endl; + } + else{ + for(unsigned int i = 0; i < 3; i++){ + for(unsigned int j = 0; j < 14*3; j++){ + std::cout << " " ; + } + if(i != 2){ + std::cout << "|" ; + } + } + } + std::cout << std::endl; + } + std::cout << std::endl; +} + +void PrintTestElementInfo(ModelPart& rModelPart){ + const ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo(); + Element::Pointer p_element = rModelPart.pGetElement(1); + array_1d perturbed_velocity = PotentialFlowUtilities::ComputePerturbedVelocity<2,3>(*p_element, r_current_process_info); + const double local_velocity_squared = inner_prod(perturbed_velocity, perturbed_velocity); + const double local_mach_squared = PotentialFlowUtilities::ComputeLocalMachNumberSquared<2, 3>(perturbed_velocity, r_current_process_info); + const double max_velocity_squared = PotentialFlowUtilities::ComputeMaximumVelocitySquared<2, 3>(r_current_process_info); + + std::cout.precision(16); + KRATOS_WATCH(perturbed_velocity) + KRATOS_WATCH(std::sqrt(max_velocity_squared)) + KRATOS_WATCH(std::sqrt(local_velocity_squared)) + KRATOS_WATCH(local_mach_squared) +} + + /** Checks the CompressiblePerturbationPotentialFlowElement. * Checks the RHS computation. */ @@ -65,42 +144,65 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePerturbationPotentialFlowElementRHS, Compr ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalCompressiblePerturbationElement(pElement); + std::array potential{1.0, 20.0, 50.0}; + AssignPotentialsToNormalCompressiblePerturbationElement(p_element, potential); // Compute RHS Vector RHS = ZeroVector(3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateRightHandSide(RHS, r_current_process_info); + p_element->CalculateRightHandSide(RHS, r_current_process_info); - std::vector reference{146.2643261263345,-122.1426284341492,-24.12169769218525}; + std::vector reference{131.4361747323354,-113.768439084114,-17.66773564822145}; KRATOS_CHECK_VECTOR_NEAR(RHS, reference, 1e-13); } -/** Checks the CompressiblePerturbationPotentialFlowElement. - * Checks the LHS computation. - */ +KRATOS_TEST_CASE_IN_SUITE(CompressiblePerturbationPotentialFlowElementRHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + + std::array potential{1.0, 220.0, 250.0}; + AssignPotentialsToNormalCompressiblePerturbationElement(p_element, potential); + + // Compute RHS + Vector RHS = ZeroVector(3); + + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + p_element->CalculateRightHandSide(RHS, r_current_process_info); + + std::vector reference{205.3219372530133,-190.7662916232804,-14.55564562973297}; + + KRATOS_CHECK_VECTOR_NEAR(RHS, reference, 1e-13); +} + +// /** Checks the CompressiblePerturbationPotentialFlowElement. +// * Checks the LHS computation. +// */ KRATOS_TEST_CASE_IN_SUITE(CompressiblePerturbationPotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { Model this_model; ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalCompressiblePerturbationElement(pElement); + std::array potential{1.0, 20.0, 50.0}; + AssignPotentialsToNormalCompressiblePerturbationElement(p_element, potential); // Compute LHS Matrix LHS = ZeroMatrix(3, 3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); - std::array reference{ 0.06114278464441542,-0.1306215050744058, 0.06947872042999037, - -0.1306215050744058, 0.6710758508914103,-0.5404543458170046, - 0.06947872042999037,-0.5404543458170046,0.4709756253870142}; + std::array reference{ 0.3316096612183497,-0.3661980912374865,0.03458843001913683, + -0.3661980912374865,0.9850616437217248,-0.6188635524842382, + 0.03458843001913683,-0.6188635524842382,0.5842751224651014}; for (unsigned int i = 0; i < LHS.size1(); i++) { for (unsigned int j = 0; j < LHS.size2(); j++) { @@ -109,79 +211,164 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePerturbationPotentialFlowElementLHS, Compr } } -/** Checks the CompressiblePerturbationPotentialFlowElement. - * Tests the LHS computation. - */ -KRATOS_TEST_CASE_IN_SUITE(PingCompressiblePerturbationPotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { +KRATOS_TEST_CASE_IN_SUITE(CompressiblePerturbationPotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { Model this_model; ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - const unsigned int number_of_nodes = pElement->GetGeometry().size(); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalCompressiblePerturbationElement(pElement); + std::array potential{1.0, 220.0, 250.0}; + AssignPotentialsToNormalCompressiblePerturbationElement(p_element, potential); - Vector RHS_original = ZeroVector(number_of_nodes); - Matrix LHS_original = ZeroMatrix(number_of_nodes, number_of_nodes); - Matrix LHS_finite_diference = ZeroMatrix(number_of_nodes, number_of_nodes); - Matrix LHS_analytical = ZeroMatrix(number_of_nodes, number_of_nodes); + // Compute LHS + Matrix LHS = ZeroMatrix(3, 3); - // Compute original RHS and LHS const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); + + std::array reference{ 0.4851881876577658,-0.4851881876577658,0, + -0.4851881876577658,0.9703763753155316,-0.4851881876577658, + 0,-0.4851881876577658,0.4851881876577658}; + + for (unsigned int i = 0; i < LHS.size1(); i++) { + for (unsigned int j = 0; j < LHS.size2(); j++) { + KRATOS_CHECK_NEAR(LHS(i, j), reference[i * 3 + j], 1e-16); + } + } +} + +void ComputeElementalSensitivitiesMatrixRow(ModelPart& rModelPart, double delta, unsigned int row, Matrix& rLHS_original, Vector& rRHS_original, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical){ + Element::Pointer p_element = rModelPart.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + // Compute pinged LHS and RHS + Vector RHS_pinged = ZeroVector(number_of_nodes); + Matrix LHS_pinged = ZeroMatrix(number_of_nodes, number_of_nodes); + const ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo(); + p_element->CalculateLocalSystem(LHS_pinged, RHS_pinged, r_current_process_info); + + for(unsigned int k = 0; k < rLHS_original.size2(); k++){ + // Compute the finite difference estimate of the sensitivity + rLHS_finite_diference( k, row) = -(RHS_pinged(k)-rRHS_original(k)) / delta; + // Compute the average of the original and pinged analytic sensitivities + rLHS_analytical( k, row) = 0.5 * (rLHS_original(k,row) + LHS_pinged(k,row)); + } + +} + +void ComputeElementalSensitivities(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential){ + Element::Pointer p_element = rModelPart.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + AssignPotentialsToNormalCompressiblePerturbationElement(p_element, rPotential); + + // Compute original RHS and LHS + Vector RHS_original = ZeroVector(number_of_nodes); + Matrix LHS_original = ZeroMatrix(number_of_nodes, number_of_nodes); + const ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo(); + p_element->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); double delta = 1e-3; for(unsigned int i = 0; i < number_of_nodes; i++){ // Pinging - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; - - Vector RHS_pinged = ZeroVector(number_of_nodes); - Matrix LHS_pinged = ZeroMatrix(number_of_nodes, number_of_nodes); - // Compute pinged LHS and RHS - pElement->CalculateLocalSystem(LHS_pinged, RHS_pinged, r_current_process_info); - - for(unsigned int k = 0; k < number_of_nodes; k++){ - // Compute the finite difference estimate of the sensitivity - LHS_finite_diference( k, i) = -(RHS_pinged(k)-RHS_original(k)) / delta; - // Compute the average of the original and pinged analytic sensitivities - LHS_analytical( k, i) = 0.5 * (LHS_original(k,i) + LHS_pinged(k,i)); - } + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; + + ComputeElementalSensitivitiesMatrixRow(rModelPart, delta, i, LHS_original, RHS_original, rLHS_finite_diference, rLHS_analytical); // Unpinging - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; } +} + +void ComputeWakeElementalSensitivities(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential){ + Element::Pointer p_element = rModelPart.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); - for (unsigned int i = 0; i < LHS_finite_diference.size1(); i++) { - for (unsigned int j = 0; j < LHS_finite_diference.size2(); j++) { - KRATOS_CHECK_NEAR(LHS_finite_diference(i,j), LHS_analytical(i,j), 1e-10); + BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; + + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, rPotential); + + // Compute original RHS and LHS + Vector RHS_original = ZeroVector(2*number_of_nodes); + Matrix LHS_original = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + const ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo(); + p_element->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); + + double delta = 1e-3; + for(unsigned int i = 0; i < 2*number_of_nodes; i++){ + if(i < number_of_nodes){ + // Pinging + if (distances(i) > 0.0) + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; + else + p_element->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) += delta; + + ComputeElementalSensitivitiesMatrixRow(rModelPart, delta, i, LHS_original, RHS_original, rLHS_finite_diference, rLHS_analytical); + + // Unpinging + if (distances(i) > 0.0) + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; + else + p_element->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) -= delta; + } + else{ + // Pinging + if (distances(i-number_of_nodes) > 0.0) + p_element->GetGeometry()[i-number_of_nodes].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) += delta; + else + p_element->GetGeometry()[i-number_of_nodes].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; + + ComputeElementalSensitivitiesMatrixRow(rModelPart, delta, i, LHS_original, RHS_original, rLHS_finite_diference, rLHS_analytical); + + // Unpinging + if (distances(i-number_of_nodes) > 0.0) + p_element->GetGeometry()[i-number_of_nodes].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) -= delta; + else + p_element->GetGeometry()[i-number_of_nodes].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; } } } -BoundedVector AssignDistancesToPerturbationCompressibleElement() -{ - BoundedVector distances; - distances(0) = 1.0; - distances(1) = -1.0; - distances(2) = -1.0; - return distances; +/** Checks the CompressiblePerturbationPotentialFlowElement. + * Tests the LHS computation. + */ +KRATOS_TEST_CASE_IN_SUITE(PingCompressiblePerturbationPotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + std::array potential{1.0, 20.0, 50.0}; + + Matrix LHS_finite_diference = ZeroMatrix(number_of_nodes, number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(number_of_nodes, number_of_nodes); + + ComputeElementalSensitivities(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); } -void AssignPotentialsToWakeCompressiblePerturbationElement(Element::Pointer pElement, const array_1d& rDistances, const std::array& rPotential) -{ - for (unsigned int i = 0; i < 3; i++){ - if (rDistances(i) > 0.0) - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i]; - else - pElement->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = rPotential[i]; - } - for (unsigned int i = 0; i < 3; i++){ - if (rDistances(i) < 0.0) - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i+3]; - else - pElement->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = rPotential[i+3]; - } +KRATOS_TEST_CASE_IN_SUITE(PingCompressiblePerturbationPotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + std::array potential{1.2495, 94.1948, 182.149583}; + + Matrix LHS_finite_diference = ZeroMatrix(number_of_nodes, number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(number_of_nodes, number_of_nodes); + + ComputeElementalSensitivities(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); } KRATOS_TEST_CASE_IN_SUITE(WakeCompressiblePerturbationPotentialFlowElementRHS, CompressiblePotentialApplicationFastSuite) { @@ -189,23 +376,107 @@ KRATOS_TEST_CASE_IN_SUITE(WakeCompressiblePerturbationPotentialFlowElementRHS, C ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); + + BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); + + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; + + const std::array potential{1.0, 31.0, 150.0, 6.0, 75.0, 55.0}; + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, potential); + + // Compute RHS and LHS + Vector RHS = ZeroVector(6); + + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + p_element->CalculateRightHandSide(RHS, r_current_process_info); + + std::vector reference{127.1146544469925,109.025,-85.1375,23.8875,-154.8303022595422,10.56213263248122}; + + KRATOS_CHECK_VECTOR_NEAR(RHS, reference, 1e-13); +} + +KRATOS_TEST_CASE_IN_SUITE(WakeCompressiblePerturbationPotentialFlowElementRHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; - const std::array potential{1.0, 101.0, 150.0, 6.0, 105.0, 155.0}; - AssignPotentialsToWakeCompressiblePerturbationElement(pElement, distances, potential); + const std::array potential{1.0, 151.0, 190.0, 6.0, 165.0, 195.0}; + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, potential); // Compute RHS and LHS Vector RHS = ZeroVector(6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateRightHandSide(RHS, r_current_process_info); + p_element->CalculateRightHandSide(RHS, r_current_process_info); - std::vector reference{146.392649744264,-0.9625396130203431,0.4812698065101715,-0.4812698065101715,-121.8478896122452,-24.06349032550858}; + std::vector reference{171.8439523046275,11.025,-5.5125,5.5125,-161.6550003638144,-14.55564562973297}; + + KRATOS_CHECK_VECTOR_NEAR(RHS, reference, 1e-13); +} + +KRATOS_TEST_CASE_IN_SUITE(WakeStructureCompressiblePerturbationPotentialFlowElementRHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); + + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; + p_element->Set(STRUCTURE); + p_element->GetGeometry()[number_of_nodes-1].SetValue(TRAILING_EDGE, true); + + const std::array potential{1.0, 31.0, 150.0, 6.0, 75.0, 55.0}; + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, potential); + + // Compute RHS and LHS + Vector RHS = ZeroVector(6); + + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + p_element->CalculateRightHandSide(RHS, r_current_process_info); + + std::vector reference{127.1146544469925,109.025,-16.14852237508765,23.8875,-154.8303022595422,7.921599474360912}; + + KRATOS_CHECK_VECTOR_NEAR(RHS, reference, 1e-13); +} + +KRATOS_TEST_CASE_IN_SUITE(WakeStructureCompressiblePerturbationPotentialFlowElementRHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); + + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; + p_element->Set(STRUCTURE); + p_element->GetGeometry()[number_of_nodes-1].SetValue(TRAILING_EDGE, true); + + const std::array potential{1.0, 151.0, 190.0, 6.0, 165.0, 195.0}; + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, potential); + + // Compute RHS and LHS + Vector RHS = ZeroVector(6); + + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + p_element->CalculateRightHandSide(RHS, r_current_process_info); + + std::vector reference{171.8439523046275,11.025,-4.730584829663217,5.5125,-161.6550003638144,-10.91673422229973}; KRATOS_CHECK_VECTOR_NEAR(RHS, reference, 1e-13); } @@ -215,29 +486,56 @@ KRATOS_TEST_CASE_IN_SUITE(WakeCompressiblePerturbationPotentialFlowElementLHS, C ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); + + BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); + + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; + + const std::array potential{1.0, 31.0, 150.0, 6.0, 75.0, 55.0}; + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, potential); + + // Compute LHS + Matrix LHS = ZeroMatrix(6, 6); + + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); + + // Check the LHS values + std::array reference{0.2730300317674839,-0.4101190902695764,0.1370890585020925,0,0,0,-0.6125,1.225,-0.6125,0.6125,-1.225,0.6125,0,-0.6125,0.6125,-0,0.6125,-0.6125,-0.6125,0.6125,-0,0.6125,-0.6125,0,0,0,0,-0.1405503745970895,0.6402833143676492,-0.4997329397705597,0,0,0,-0.02643811017306578,-0.4997329397705597,0.5261710499436255}; + + for (unsigned int i = 0; i < LHS.size1(); i++) { + for (unsigned int j = 0; j < LHS.size2(); j++) { + KRATOS_CHECK_NEAR(LHS(i, j), reference[6 * i + j], 1e-16); + } + } +} + +KRATOS_TEST_CASE_IN_SUITE(WakeCompressiblePerturbationPotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; - const std::array potential{1.0, 100.0, 150.0, 6.0, 105.0, 155.0}; - AssignPotentialsToWakeCompressiblePerturbationElement(pElement, distances, potential); + const std::array potential{1.0, 151.0, 190.0, 6.0, 165.0, 195.0}; + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, potential); // Compute LHS Matrix LHS = ZeroMatrix(6, 6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); // Check the LHS values - std::array reference{0.06114278464441542,-0.1306215050744058,0.06947872042999037,0,0,0, - -0.1306215050744058,0.6710758508914103,-0.5404543458170046,0.1306215050744058,-0.6710758508914103,0.5404543458170046, - 0.06947872042999037,-0.5404543458170046,0.4709756253870142,-0.06947872042999037,0.5404543458170046,-0.4709756253870142, - -0.06114278464441542,0.1306215050744058,-0.06947872042999037,0.06114278464441542,-0.1306215050744058,0.06947872042999037, - 0,0,0,-0.1306215050744058,0.6710758508914103,-0.5404543458170046, - 0,0,0,0.06947872042999037,-0.5404543458170046,0.4709756253870142}; + std::array reference{0.4851881876577658,-0.4851881876577658,0,0,0,0,-0.6125,1.225,-0.6125,0.6125, + -1.225,0.6125,0,-0.6125,0.6125,-0,0.6125,-0.6125,-0.6125,0.6125,-0,0.6125,-0.6125,0,0,0,0,-0.4851881876577658,0.9703763753155316,-0.4851881876577658,0,0,0,0,-0.4851881876577658,0.4851881876577658}; for (unsigned int i = 0; i < LHS.size1(); i++) { for (unsigned int j = 0; j < LHS.size2(); j++) { @@ -246,5 +544,159 @@ KRATOS_TEST_CASE_IN_SUITE(WakeCompressiblePerturbationPotentialFlowElementLHS, C } } +KRATOS_TEST_CASE_IN_SUITE(WakeStructureCompressiblePerturbationPotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); + + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; + p_element->Set(STRUCTURE); + p_element->GetGeometry()[number_of_nodes-1].SetValue(TRAILING_EDGE, true); + + const std::array potential{1.0, 31.0, 150.0, 6.0, 75.0, 55.0}; + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, potential); + + // Compute LHS + Matrix LHS = ZeroMatrix(6, 6); + + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); + + // Check the LHS values + std::array reference{0.2730300317674839,-0.4101190902695764,0.1370890585020925,0,0,0,-0.6125,1.225, + -0.6125,0.6125,-1.225,0.6125,0.03427226462552314,-0.1525584723345968,0.1182862077090737,0,0,0,-0.6125,0.6125, + -0,0.6125,-0.6125,0,0,0,0,-0.1405503745970895,0.6402833143676492,-0.4997329397705597,0,0,0,-0.01982858262979934,-0.3747997048279197,0.3946282874577191}; + + for (unsigned int i = 0; i < LHS.size1(); i++) { + for (unsigned int j = 0; j < LHS.size2(); j++) { + KRATOS_CHECK_NEAR(LHS(i, j), reference[6 * i + j], 1e-16); + } + } +} + +KRATOS_TEST_CASE_IN_SUITE(WakeStructureCompressiblePerturbationPotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + BoundedVector distances = AssignDistancesToPerturbationCompressibleElement(); + + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; + p_element->Set(STRUCTURE); + p_element->GetGeometry()[number_of_nodes-1].SetValue(TRAILING_EDGE, true); + + const std::array potential{1.0, 151.0, 190.0, 6.0, 165.0, 195.0}; + AssignPotentialsToWakeCompressiblePerturbationElement(p_element, distances, potential); + + // Compute LHS + Matrix LHS = ZeroMatrix(6, 6); + + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); + + // Check the LHS values + std::array reference{0.4851881876577658,-0.4851881876577658,0,0,0,0,-0.6125,1.225,-0.6125,0.6125, + -1.225,0.6125,0,-0.1212970469144414,0.1212970469144414,0,0,0,-0.6125,0.6125,-0,0.6125,-0.6125,0,0,0,0, + -0.4851881876577658,0.9703763753155316,-0.4851881876577658,0,0,0,0,-0.3638911407433243,0.3638911407433243}; + + for (unsigned int i = 0; i < LHS.size1(); i++) { + for (unsigned int j = 0; j < LHS.size2(); j++) { + KRATOS_CHECK_NEAR(LHS(i, j), reference[6 * i + j], 1e-16); + } + } +} + +KRATOS_TEST_CASE_IN_SUITE(PingWakeCompressiblePerturbationPotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + const std::array potential{1.0, 40.0, 35.0, 6.0, 26.0, 14.0}; + + Matrix LHS_finite_diference = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + + ComputeWakeElementalSensitivities(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +KRATOS_TEST_CASE_IN_SUITE(PingWakeCompressiblePerturbationPotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + const std::array potential{1.285837, 170.29384, 135.1583, 6.0, 196.345, 114.0}; + + Matrix LHS_finite_diference = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + + ComputeWakeElementalSensitivities(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +KRATOS_TEST_CASE_IN_SUITE(PingWakeStructureCompressiblePerturbationPotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + p_element->Set(STRUCTURE); + p_element->GetGeometry()[number_of_nodes-1].SetValue(TRAILING_EDGE, true); + + const std::array potential{1.285837, 30.29384, 35.1583, 6.0, 46.345, 64.0}; + + Matrix LHS_finite_diference = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + + ComputeWakeElementalSensitivities(model_part, LHS_finite_diference, LHS_analytical, potential); + + PrintTestElementInfo(model_part); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +KRATOS_TEST_CASE_IN_SUITE(PingWakeStructureCompressiblePerturbationPotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressiblePerturbationElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + p_element->Set(STRUCTURE); + p_element->GetGeometry()[number_of_nodes-1].SetValue(TRAILING_EDGE, true); + + const std::array potential{1.285837, 170.29384, 135.1583, 6.0, 196.345, 114.0}; + + Matrix LHS_finite_diference = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + + ComputeWakeElementalSensitivities(model_part, LHS_finite_diference, LHS_analytical, potential); + + PrintTestElementInfo(model_part); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + } // namespace Testing } // namespace Kratos. diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_compressible_potential_element.cpp b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_compressible_potential_element.cpp index ad0b29d5b710..48202a5241fe 100644 --- a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_compressible_potential_element.cpp +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_compressible_potential_element.cpp @@ -18,6 +18,7 @@ #include "fluid_dynamics_application_variables.h" #include "custom_elements/compressible_potential_flow_element.h" #include "custom_elements/embedded_compressible_potential_flow_element.h" +#include "tests/cpp_tests/test_utilities.h" namespace Kratos { namespace Testing { @@ -41,6 +42,7 @@ void GenerateCompressibleElement(ModelPart& rModelPart) { rModelPart.GetProcessInfo()[HEAT_CAPACITY_RATIO] = 1.4; rModelPart.GetProcessInfo()[SOUND_VELOCITY] = 340.0; rModelPart.GetProcessInfo()[MACH_LIMIT] = 0.94; + rModelPart.GetProcessInfo()[MACH_SQUARED_LIMIT] = 0.8836; // Geometry creation rModelPart.CreateNewNode(1, 0.0, 0.0, 0.0); @@ -68,6 +70,7 @@ void GenerateCompressibleEmbeddedElement(ModelPart& rModelPart) { rModelPart.GetProcessInfo()[HEAT_CAPACITY_RATIO] = 1.4; rModelPart.GetProcessInfo()[SOUND_VELOCITY] = 340.0; rModelPart.GetProcessInfo()[MACH_LIMIT] = 0.94; + rModelPart.GetProcessInfo()[MACH_SQUARED_LIMIT] = 0.8836; // Geometry creation rModelPart.CreateNewNode(1, 0.0, 0.0, 0.0); @@ -77,7 +80,7 @@ void GenerateCompressibleEmbeddedElement(ModelPart& rModelPart) { rModelPart.CreateNewElement("EmbeddedCompressiblePotentialFlowElement2D3N", 1, elemNodes, pElemProp); } -/** Checks the IncompressiblePotentialFlowElement element. +/** Checks the CompressiblePotentialFlowElement element. * Checks the LHS and RHS computation. */ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementRHS, CompressiblePotentialApplicationFastSuite) { @@ -85,7 +88,7 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementRHS, CompressiblePoten ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressibleElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); // Define the nodal values std::array potential; @@ -94,14 +97,14 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementRHS, CompressiblePoten potential[2] = 3.0; for (unsigned int i = 0; i < 3; i++) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; } // Compute RHS and LHS Vector RHS = ZeroVector(3); Matrix LHS = ZeroMatrix(3, 3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); std::vector reference({0.615561780, 0.0, -0.615561780}); @@ -110,7 +113,7 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementRHS, CompressiblePoten } } -/** Checks the IncompressiblePotentialFlowElement element. +/** Checks the CompressiblePotentialFlowElement element. * Checks the LHS and RHS computation. */ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { @@ -118,7 +121,7 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementLHS, CompressiblePoten ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressibleElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); // Define the nodal values std::array potential; @@ -127,14 +130,14 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementLHS, CompressiblePoten potential[2] = 3.0; for (unsigned int i = 0; i < 3; i++) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; } // Compute RHS and LHS Vector RHS = ZeroVector(3); Matrix LHS = ZeroMatrix(3, 3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); std::array reference{0.615556466, -0.615561780, 5.314318652e-06, -0.615561780, 1.231123561, -0.615561780, 5.314318652e-06, -0.615561780, 0.615556466}; @@ -145,12 +148,48 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementLHS, CompressiblePoten } } +KRATOS_TEST_CASE_IN_SUITE(PingCompressiblePotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressibleElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + const std::array potential{1.0, 20.0, 50.0}; + + Matrix LHS_finite_diference = ZeroMatrix(number_of_nodes, number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(number_of_nodes, number_of_nodes); + + PotentialFlowTestUtilities::ComputeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +KRATOS_TEST_CASE_IN_SUITE(PingCompressiblePotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressibleElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + std::array potential{1.2495, 794.1948, 582.149583}; + + Matrix LHS_finite_diference = ZeroMatrix(number_of_nodes, number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(number_of_nodes, number_of_nodes); + + PotentialFlowTestUtilities::ComputeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + KRATOS_TEST_CASE_IN_SUITE(EmbeddedCompressiblePotentialFlowElementCalculateLocalSystemRHS, CompressiblePotentialApplicationFastSuite) { Model this_model; ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressibleEmbeddedElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); // Define the nodal values std::array potential{1.0, 2.0, 3.0}; @@ -158,8 +197,8 @@ KRATOS_TEST_CASE_IN_SUITE(EmbeddedCompressiblePotentialFlowElementCalculateLocal std::array level_set{1.0, -1.0, -1.0}; for (unsigned int i = 0; i < 3; i++) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; - pElement->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set[i]; } // Compute RHS and LHS @@ -167,7 +206,7 @@ KRATOS_TEST_CASE_IN_SUITE(EmbeddedCompressiblePotentialFlowElementCalculateLocal Matrix LHS = ZeroMatrix(3, 3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); std::vector reference{0.125625, 0.0, -0.125625}; @@ -179,15 +218,15 @@ KRATOS_TEST_CASE_IN_SUITE(EmbeddedCompressiblePotentialFlowElementCalculateLocal ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressibleEmbeddedElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); // Define the nodal values std::array potential{1.0, 2.0, 3.0}; // Define the distance values std::array level_set{1.0, -1.0, -1.0}; for (unsigned int i = 0; i < 3; i++) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; - pElement->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set[i]; } // Compute RHS and LHS @@ -195,9 +234,9 @@ KRATOS_TEST_CASE_IN_SUITE(EmbeddedCompressiblePotentialFlowElementCalculateLocal Matrix LHS = ZeroMatrix(3, 3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); - std::array reference_array{0.251249, -0.25125, 1.08455e-06, -0.25125, 0.502499, -0.25125, 1.08455e-06, -0.25125, 0.251249}; + std::array reference_array{0.125624, -0.125625, 1.08455e-06, -0.125625, 0.25125, -0.125625, 1.08455e-06, -0.125625, 0.125624}; // Copying to a 3x3 matrix to check against LHS Matrix reference(3, 3); for (unsigned int i = 0; i < reference.size1(); i++) { @@ -209,12 +248,60 @@ KRATOS_TEST_CASE_IN_SUITE(EmbeddedCompressiblePotentialFlowElementCalculateLocal KRATOS_CHECK_MATRIX_NEAR(LHS, reference, 1e-6); } +KRATOS_TEST_CASE_IN_SUITE(PingEmbeddedCompressiblePotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressibleEmbeddedElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + // Define the distance values + std::array level_set{1.0, -1.0, -1.0}; + for (unsigned int i = 0; i < 3; i++) { + p_element->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set[i]; + } + + const std::array potential{1.0, 20.0, 50.0}; + + Matrix LHS_finite_diference = ZeroMatrix(number_of_nodes, number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(number_of_nodes, number_of_nodes); + + PotentialFlowTestUtilities::ComputeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +KRATOS_TEST_CASE_IN_SUITE(PingEmbeddedCompressiblePotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressibleEmbeddedElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + // Define the distance values + std::array level_set{1.0, -1.0, -1.0}; + for (unsigned int i = 0; i < 3; i++) { + p_element->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set[i]; + } + + std::array potential{1.2495, 794.1948, 582.149583}; + + Matrix LHS_finite_diference = ZeroMatrix(number_of_nodes, number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(number_of_nodes, number_of_nodes); + + PotentialFlowTestUtilities::ComputeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementRHSWake, CompressiblePotentialApplicationFastSuite) { Model this_model; ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressibleElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); // Define the nodal values std::array potential; @@ -227,23 +314,23 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementRHSWake, CompressibleP distances(1) = -1.0; distances(2) = -1.0; - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; for (unsigned int i = 0; i < 3; i++) { if (distances(i) > 0.0) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; } else { - pElement->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = potential[i]; } } for (unsigned int i = 0; i < 3; i++) { if (distances(i) < 0.0) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i] + 5; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i] + 5; } else { - pElement->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = potential[i] + 5; + p_element->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = potential[i] + 5; } } @@ -252,7 +339,7 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementRHSWake, CompressibleP Matrix LHS = ZeroMatrix(6, 6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); std::array reference{0.615561780, 0.0, 0.0, 0.0, 0.0, -0.615561780}; @@ -266,7 +353,7 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementLHSWake, CompressibleP ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressibleElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); // Define the nodal values std::array potential; @@ -279,23 +366,23 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementLHSWake, CompressibleP distances(1) = -1.0; distances(2) = -1.0; - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; for (unsigned int i = 0; i < 3; i++) { if (distances(i) > 0.0) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; } else { - pElement->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = potential[i]; } } for (unsigned int i = 0; i < 3; i++) { if (distances(i) < 0.0) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i] + 5; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i] + 5; } else { - pElement->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = potential[i] + 5; + p_element->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = potential[i] + 5; } } @@ -304,16 +391,16 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementLHSWake, CompressibleP Matrix LHS = ZeroMatrix(6, 6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); // Check the RHS values (the RHS is computed as the LHS x previous_solution, // hence, it is assumed that if the RHS is correct, the LHS is correct as well) - std::array reference{0.615556466,-0.615561780,5.314318652e-06,0.0,0.0,0.0, - -0.615561780,1.231123561,-0.615561780,0.615561780,-1.231123561,0.615561780, - 5.314318652e-06,-0.615561780, 0.615556466,-5.314318652e-06,0.615561780, -0.615556466, - -0.615556466, 0.615561780,-5.314318652e-06,0.615556466, -0.615561780,5.314318652e-06, - 0.0,0.0,0.0,-0.615561780,1.231123561,-0.615561780, - 0.0,0.0,0.0,5.314318652e-06,-0.615561780,0.615556466}; + std::array reference{0.6155564666297989,-0.6155617809484512,5.314318652279458e-06,0,0,0, + -0.6125,1.225,-0.6125,0.6125,-1.225,0.6125, + 0,-0.6125,0.6125,-0,0.6125,-0.6125, + -0.6125,0.6125,-0,0.6125,-0.6125,0, + 0,0,0,-0.6155617809484512,1.231123561896902,-0.6155617809484512, + 0,0,0,5.314318652279458e-06,-0.6155617809484512,0.6155564666297989}; for (unsigned int i = 0; i < LHS.size1(); i++) { for (unsigned int j = 0; j < LHS.size2(); j++) { @@ -322,7 +409,85 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementLHSWake, CompressibleP } } -/** Checks the IncompressiblePotentialFlowElement element. +KRATOS_TEST_CASE_IN_SUITE(PingWakeCompressiblePotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressibleElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + const std::array potential{1.0, 40.0, 35.0, 6.0, 26.0, 14.0}; + + Matrix LHS_finite_diference = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + + PotentialFlowTestUtilities::ComputeWakeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +KRATOS_TEST_CASE_IN_SUITE(PingWakeCompressiblePotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressibleElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + const std::array potential{1.285837, 570.29384, 635.1583, 6.0, 796.345, 814.254}; + + Matrix LHS_finite_diference = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + + PotentialFlowTestUtilities::ComputeWakeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +KRATOS_TEST_CASE_IN_SUITE(PingWakeStructureCompressiblePotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressibleElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + p_element->Set(STRUCTURE); + p_element->GetGeometry()[number_of_nodes-1].SetValue(TRAILING_EDGE, true); + + const std::array potential{1.285837, 30.29384, 35.1583, 6.0, 46.345, 64.0}; + + Matrix LHS_finite_diference = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + + PotentialFlowTestUtilities::ComputeWakeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +KRATOS_TEST_CASE_IN_SUITE(PingWakeStructureCompressiblePotentialFlowElementLHSClamping, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateCompressibleElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + p_element->Set(STRUCTURE); + p_element->GetGeometry()[number_of_nodes-1].SetValue(TRAILING_EDGE, true); + + const std::array potential{1.285837, 170.29384, 135.1583, 6.0, 196.345, 114.0}; + + Matrix LHS_finite_diference = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(2*number_of_nodes, 2*number_of_nodes); + + PotentialFlowTestUtilities::ComputeWakeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); +} + +/** Checks the CompressiblePotentialFlowElement element. * Checks the EquationIdVector. */ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementEquationIdVector, CompressiblePotentialApplicationFastSuite) { @@ -330,22 +495,22 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementEquationIdVector, Comp ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressibleElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); for (unsigned int i = 0; i < 3; i++) { - pElement->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); } Element::DofsVectorType ElementalDofList; const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->GetDofList(ElementalDofList, r_current_process_info); + p_element->GetDofList(ElementalDofList, r_current_process_info); for (int i = 0; i < 3; i++) { ElementalDofList[i]->SetEquationId(i); } Element::EquationIdVectorType EquationIdVector; - pElement->EquationIdVector(EquationIdVector, r_current_process_info); + p_element->EquationIdVector(EquationIdVector, r_current_process_info); // Check the EquationIdVector values for (unsigned int i = 0; i < EquationIdVector.size(); i++) { @@ -353,7 +518,7 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementEquationIdVector, Comp } } -/** Checks the IncompressiblePotentialFlowElement element. +/** Checks the CompressiblePotentialFlowElement element. * Checks the EquationIdVector for the Wake. */ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementEquationIdVectorWake, CompressiblePotentialApplicationFastSuite) { @@ -361,30 +526,30 @@ KRATOS_TEST_CASE_IN_SUITE(CompressiblePotentialFlowElementEquationIdVectorWake, ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateCompressibleElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); Vector distances(3); distances(0) = -0.5; distances(1) = -0.5; distances(2) = 0.5; - pElement->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); + p_element->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); for (unsigned int i = 0; i < 3; i++) { - pElement->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); - pElement->GetGeometry()[i].AddDof(AUXILIARY_VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(AUXILIARY_VELOCITY_POTENTIAL); } Element::DofsVectorType ElementalDofList; const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->GetDofList(ElementalDofList, r_current_process_info); + p_element->GetDofList(ElementalDofList, r_current_process_info); for (int i = 0; i < 6; i++) { ElementalDofList[i]->SetEquationId(i); } Element::EquationIdVectorType EquationIdVector; - pElement->EquationIdVector(EquationIdVector, r_current_process_info); + p_element->EquationIdVector(EquationIdVector, r_current_process_info); // Check the EquationIdVector values for (unsigned int i = 0; i < EquationIdVector.size(); i++) { diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_incompressible_perturbation_potential_element.cpp b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_incompressible_perturbation_potential_element.cpp index 8744afb616f8..0870156e37c4 100644 --- a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_incompressible_perturbation_potential_element.cpp +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_incompressible_perturbation_potential_element.cpp @@ -91,15 +91,15 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateIncompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalPerturbationElement(pElement); + AssignPotentialsToNormalPerturbationElement(p_element); // Compute RHS Vector RHS = ZeroVector(3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateRightHandSide(RHS, r_current_process_info); + p_element->CalculateRightHandSide(RHS, r_current_process_info); // Check the RHS values std::vector reference{5.5, -5, -0.5}; @@ -116,15 +116,15 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateIncompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalPerturbationElement(pElement); + AssignPotentialsToNormalPerturbationElement(p_element); // Compute LHS Matrix LHS = ZeroMatrix(3,3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); // Check the LHS values std::array reference{0.5, -0.5, 0, -0.5, 1, -0.5, 0.0, -0.5, 0.5}; @@ -142,21 +142,21 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateIncompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); BoundedVector distances = AssignDistancesToPerturbationElement(); - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; const std::array potential{1.5348, 2.31532, 3.2874, 4.1642, 6.8254, 5.174}; - AssignPotentialsToWakePerturbationElement(pElement, distances, potential); + AssignPotentialsToWakePerturbationElement(p_element, distances, potential); // Compute RHS Vector RHS = ZeroVector(6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateRightHandSide(RHS, r_current_process_info); + p_element->CalculateRightHandSide(RHS, r_current_process_info); // Check the RHS values std::vector reference{5.39026,2.252080000000001,-1.31174,0.9403400000000008,-7.1563,0.8256999999999999}; @@ -170,21 +170,21 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateIncompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); BoundedVector distances = AssignDistancesToPerturbationElement(); - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; const std::array potential{1.0, 2.0, 3.0, 6.0, 7.0, 8.0}; - AssignPotentialsToWakePerturbationElement(pElement, distances, potential); + AssignPotentialsToWakePerturbationElement(p_element, distances, potential); // Compute LHS Matrix LHS = ZeroMatrix(6,6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); // Check the LHS values std::array reference @@ -210,20 +210,20 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateIncompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); for (unsigned int i = 0; i < 3; i++) - pElement->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); Element::DofsVectorType ElementalDofList; const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->GetDofList(ElementalDofList, r_current_process_info); + p_element->GetDofList(ElementalDofList, r_current_process_info); for (int i = 0; i < 3; i++) ElementalDofList[i]->SetEquationId(i); Element::EquationIdVectorType EquationIdVector; - pElement->EquationIdVector(EquationIdVector, r_current_process_info); + p_element->EquationIdVector(EquationIdVector, r_current_process_info); // Check the EquationIdVector values for (unsigned int i = 0; i < EquationIdVector.size(); i++) { @@ -241,26 +241,26 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateIncompressiblePerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); BoundedVector distances = AssignDistancesToPerturbationElement(); - pElement->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); + p_element->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); for (unsigned int i = 0; i < 3; i++) { - pElement->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); - pElement->GetGeometry()[i].AddDof(AUXILIARY_VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(AUXILIARY_VELOCITY_POTENTIAL); } Element::DofsVectorType ElementalDofList; const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->GetDofList(ElementalDofList, r_current_process_info); + p_element->GetDofList(ElementalDofList, r_current_process_info); for (int i = 0; i < 6; i++) ElementalDofList[i]->SetEquationId(i); Element::EquationIdVectorType EquationIdVector; - pElement->EquationIdVector(EquationIdVector, r_current_process_info); + p_element->EquationIdVector(EquationIdVector, r_current_process_info); //Check the EquationIdVector values for (unsigned int i = 0; i < EquationIdVector.size(); i++) { diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_incompressible_potential_element.cpp b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_incompressible_potential_element.cpp index 4d1f4a72c8c9..dc6ec052bf70 100644 --- a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_incompressible_potential_element.cpp +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_incompressible_potential_element.cpp @@ -19,6 +19,7 @@ #include "custom_elements/incompressible_potential_flow_element.h" #include "custom_elements/embedded_incompressible_potential_flow_element.h" #include "custom_utilities/potential_flow_utilities.h" +#include "tests/cpp_tests/test_utilities.h" namespace Kratos { namespace Testing { @@ -122,16 +123,16 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalElement(pElement); + AssignPotentialsToNormalElement(p_element); // Compute RHS and LHS Vector RHS = ZeroVector(3); Matrix LHS = ZeroMatrix(3, 3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); // Check the RHS values (the RHS is computed as the LHS x previous_solution, // hence, it is assumed that if the RHS is correct, the LHS is correct as well) @@ -148,21 +149,21 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); BoundedVector distances = AssignDistances(); - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; - AssignPotentialsToWakeElement(pElement, distances); + AssignPotentialsToWakeElement(p_element, distances); // Compute RHS and LHS Vector RHS = ZeroVector(6); Matrix LHS = ZeroMatrix(6, 6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); // Check the RHS values (the RHS is computed as the LHS x previous_solution, // hence, it is assumed that if the RHS is correct, the LHS is correct as well) @@ -179,9 +180,9 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateEmbeddedElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalElement(pElement); + AssignPotentialsToNormalElement(p_element); // Define the distance values Vector level_set(3); @@ -190,7 +191,7 @@ namespace Kratos { level_set(2) = -1.0; for (unsigned int i = 0; i < 3; i++){ - pElement->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set(i); + p_element->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set(i); } // Compute RHS and LHS @@ -198,7 +199,7 @@ namespace Kratos { Matrix LHS = ZeroMatrix(3, 3); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS, RHS, r_current_process_info); + p_element->CalculateLocalSystem(LHS, RHS, r_current_process_info); // Check the RHS values (the RHS is computed as the LHS x previous_solution, // hence, it is assumed that if the RHS is correct, the LHS is correct as well) @@ -209,6 +210,30 @@ namespace Kratos { } } + KRATOS_TEST_CASE_IN_SUITE(PingEmbeddedIncompressiblePotentialFlowElementLHS, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateEmbeddedElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + // Define the distance values + std::array level_set{1.0, -1.0, -1.0}; + for (unsigned int i = 0; i < 3; i++) { + p_element->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = level_set[i]; + } + + const std::array potential{1.0, 20.0, 50.0}; + + Matrix LHS_finite_diference = ZeroMatrix(number_of_nodes, number_of_nodes); + Matrix LHS_analytical = ZeroMatrix(number_of_nodes, number_of_nodes); + + PotentialFlowTestUtilities::ComputeElementalSensitivities<3>(model_part, LHS_finite_diference, LHS_analytical, potential); + + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); + } + /** Checks the IncompressiblePotentialFlowElement element. * Checks the EquationIdVector. @@ -220,20 +245,20 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); for (unsigned int i = 0; i < 3; i++) - pElement->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); Element::DofsVectorType ElementalDofList; const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->GetDofList(ElementalDofList, r_current_process_info); + p_element->GetDofList(ElementalDofList, r_current_process_info); for (int i = 0; i < 3; i++) ElementalDofList[i]->SetEquationId(i); Element::EquationIdVectorType EquationIdVector; - pElement->EquationIdVector(EquationIdVector, r_current_process_info); + p_element->EquationIdVector(EquationIdVector, r_current_process_info); // Check the EquationIdVector values for (unsigned int i = 0; i < EquationIdVector.size(); i++) { @@ -251,26 +276,26 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); BoundedVector distances = AssignDistances(); - pElement->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); + p_element->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); for (unsigned int i = 0; i < 3; i++) { - pElement->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); - pElement->GetGeometry()[i].AddDof(AUXILIARY_VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(VELOCITY_POTENTIAL); + p_element->GetGeometry()[i].AddDof(AUXILIARY_VELOCITY_POTENTIAL); } Element::DofsVectorType ElementalDofList; const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->GetDofList(ElementalDofList, r_current_process_info); + p_element->GetDofList(ElementalDofList, r_current_process_info); for (int i = 0; i < 6; i++) ElementalDofList[i]->SetEquationId(i); Element::EquationIdVectorType EquationIdVector; - pElement->EquationIdVector(EquationIdVector, r_current_process_info); + p_element->EquationIdVector(EquationIdVector, r_current_process_info); //Check the EquationIdVector values for (unsigned int i = 0; i < EquationIdVector.size(); i++) { @@ -285,13 +310,13 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); BoundedVector distances = AssignDistances(); - pElement->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); + p_element->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); - const auto returned_distances = PotentialFlowUtilities::GetWakeDistances<2, 3>(*pElement); + const auto returned_distances = PotentialFlowUtilities::GetWakeDistances<2, 3>(*p_element); std::array reference{1.0, -1.0, -1.0}; @@ -307,11 +332,11 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalElement(pElement); + AssignPotentialsToNormalElement(p_element); - auto potentials = PotentialFlowUtilities::GetPotentialOnNormalElement<2,3>(*pElement); + auto potentials = PotentialFlowUtilities::GetPotentialOnNormalElement<2,3>(*p_element); std::array reference{1.0, 2.0, 3.0}; @@ -327,15 +352,15 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); BoundedVector distances = AssignDistances(); - AssignPotentialsToWakeElement(pElement, distances); + AssignPotentialsToWakeElement(p_element, distances); array_1d potentials = - PotentialFlowUtilities::GetPotentialOnUpperWakeElement<2, 3>(*pElement, distances); + PotentialFlowUtilities::GetPotentialOnUpperWakeElement<2, 3>(*p_element, distances); std::array reference{1.0, 2.0, 3.0}; @@ -351,15 +376,15 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); BoundedVector distances = AssignDistances(); - AssignPotentialsToWakeElement(pElement, distances); + AssignPotentialsToWakeElement(p_element, distances); array_1d potentials = - PotentialFlowUtilities::GetPotentialOnLowerWakeElement<2, 3>(*pElement, distances); + PotentialFlowUtilities::GetPotentialOnLowerWakeElement<2, 3>(*p_element, distances); std::array reference{6.0, 7.0, 8.0}; @@ -375,15 +400,15 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); BoundedVector distances = AssignDistances(); - AssignPotentialsToWakeElement(pElement, distances); + AssignPotentialsToWakeElement(p_element, distances); BoundedVector potentials = - PotentialFlowUtilities::GetPotentialOnWakeElement<2, 3>(*pElement, distances); + PotentialFlowUtilities::GetPotentialOnWakeElement<2, 3>(*p_element, distances); std::array reference{1.0, 2.0, 3.0, 6.0, 7.0, 8.0}; @@ -399,11 +424,11 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalElement(pElement); + AssignPotentialsToNormalElement(p_element); - auto velocity = PotentialFlowUtilities::ComputeVelocityNormalElement<2,3>(*pElement); + auto velocity = PotentialFlowUtilities::ComputeVelocityNormalElement<2,3>(*p_element); std::array reference{1.0, 1.0}; @@ -419,15 +444,15 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); BoundedVector distances = AssignDistances(); - pElement->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); + p_element->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); - AssignPotentialsToWakeElement(pElement, distances); + AssignPotentialsToWakeElement(p_element, distances); - auto velocity = PotentialFlowUtilities::ComputeVelocityUpperWakeElement<2, 3>(*pElement); + auto velocity = PotentialFlowUtilities::ComputeVelocityUpperWakeElement<2, 3>(*p_element); std::array reference{1.0, 1.0}; @@ -443,15 +468,15 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetValue(WAKE, true); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetValue(WAKE, true); BoundedVector distances = AssignDistances(); - pElement->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); + p_element->SetValue(WAKE_ELEMENTAL_DISTANCES, distances); - AssignPotentialsToWakeElement(pElement, distances); + AssignPotentialsToWakeElement(p_element, distances); - auto velocity = PotentialFlowUtilities::ComputeVelocityLowerWakeElement<2, 3>(*pElement); + auto velocity = PotentialFlowUtilities::ComputeVelocityLowerWakeElement<2, 3>(*p_element); std::array reference{1.0, 1.0}; @@ -467,11 +492,11 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalElement(pElement); + AssignPotentialsToNormalElement(p_element); - auto velocity = PotentialFlowUtilities::ComputeVelocity<2,3>(*pElement); + auto velocity = PotentialFlowUtilities::ComputeVelocity<2,3>(*p_element); std::array reference{1.0, 1.0}; @@ -487,12 +512,12 @@ namespace Kratos { ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToNormalElement(pElement); + AssignPotentialsToNormalElement(p_element); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - double pressure_coefficient = PotentialFlowUtilities::ComputeIncompressiblePressureCoefficient<2,3>(*pElement, r_current_process_info); + double pressure_coefficient = PotentialFlowUtilities::ComputeIncompressiblePressureCoefficient<2,3>(*p_element, r_current_process_info); KRATOS_CHECK_NEAR(pressure_coefficient, 0.98, 1e-7); } diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_potential_flow_utilities.cpp b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_potential_flow_utilities.cpp index 808ca9aa752e..3a05cf4c59f5 100644 --- a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_potential_flow_utilities.cpp +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_potential_flow_utilities.cpp @@ -84,17 +84,23 @@ void AssignPerturbationPotentialsToElement(Element& rElement) { potential[i]; } +void AssignCustomPerturbationPotentialsToElement(Element& rElement, const std::array rPotential) +{ + for (unsigned int i = 0; i < 3; i++) + rElement.GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i]; +} + KRATOS_TEST_CASE_IN_SUITE(ComputePerturbedVelocity, CompressiblePotentialApplicationFastSuite) { Model this_model; ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTestingElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPerturbationPotentialsToElement(*pElement); + AssignPerturbationPotentialsToElement(*p_element); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - array_1d perturbed_velocity = PotentialFlowUtilities::ComputePerturbedVelocity<2,3>(*pElement, r_current_process_info); + array_1d perturbed_velocity = PotentialFlowUtilities::ComputePerturbedVelocity<2,3>(*p_element, r_current_process_info); KRATOS_CHECK_RELATIVE_NEAR(perturbed_velocity[0], 303.0, 1e-15); KRATOS_CHECK_RELATIVE_NEAR(perturbed_velocity[1], 50.0, 1e-15); @@ -132,19 +138,34 @@ KRATOS_TEST_CASE_IN_SUITE(ComputeMaximumVelocitySquared, CompressiblePotentialAp KRATOS_CHECK_RELATIVE_NEAR(max_velocity_squared, reference_max_velocity_squared, 1e-15); } +// Checks the function ComputeVacuumVelocitySquared from the utilities +KRATOS_TEST_CASE_IN_SUITE(ComputeVacuumVelocitySquared, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + AssignFreeStreamValues(model_part); + + const double reference_max_velocity_squared = 619616.0; + + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + const double vacuum_velocity_squared = PotentialFlowUtilities::ComputeVacuumVelocitySquared(r_current_process_info); + + KRATOS_CHECK_RELATIVE_NEAR(vacuum_velocity_squared, reference_max_velocity_squared, 1e-15); +} + // Checks the function ComputeLocalSpeedOfSound from the utilities KRATOS_TEST_CASE_IN_SUITE(ComputeLocalSpeedOfSound, CompressiblePotentialApplicationFastSuite) { Model this_model; ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTestingElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToElement(*pElement); + AssignPotentialsToElement(*p_element); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); const double local_speed_of_sound = PotentialFlowUtilities::ComputeLocalSpeedOfSound<2, 3>( - *pElement, r_current_process_info); + *p_element, r_current_process_info); KRATOS_CHECK_NEAR(local_speed_of_sound, 333.801138, 1e-6); } @@ -177,13 +198,13 @@ KRATOS_TEST_CASE_IN_SUITE(ComputeLocalMachNumber, CompressiblePotentialApplicati ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTestingElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPotentialsToElement(*pElement); + AssignPotentialsToElement(*p_element); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); const double local_mach_number = PotentialFlowUtilities::ComputeLocalMachNumber<2, 3>( - *pElement, r_current_process_info); + *p_element, r_current_process_info); KRATOS_CHECK_NEAR(local_mach_number, 0.748948914, 1e-6); } @@ -269,13 +290,13 @@ KRATOS_TEST_CASE_IN_SUITE(ComputePerturbationIncompressiblePressureCoefficient, ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTestingElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPerturbationPotentialsToElement(*pElement); + AssignPerturbationPotentialsToElement(*p_element); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); const double pressure_coefficient = PotentialFlowUtilities::ComputePerturbationIncompressiblePressureCoefficient<2, 3>( - *pElement, r_current_process_info); + *p_element, r_current_process_info); KRATOS_CHECK_NEAR(pressure_coefficient, -1.266171664744329, 1e-15); } @@ -286,30 +307,54 @@ KRATOS_TEST_CASE_IN_SUITE(ComputePerturbationCompressiblePressureCoefficient, Co ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTestingElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPerturbationPotentialsToElement(*pElement); + AssignPerturbationPotentialsToElement(*p_element); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); const double pressure_coefficient = PotentialFlowUtilities::ComputePerturbationCompressiblePressureCoefficient<2, 3>( - *pElement, r_current_process_info); + *p_element, r_current_process_info); KRATOS_CHECK_NEAR(pressure_coefficient, -1.128385779511008, 1e-15); } +// Checks the function ComputePerturbationCompressiblePressureCoefficient from the utilities +KRATOS_TEST_CASE_IN_SUITE(ComputePerturbationCompressiblePressureCoefficientClamped, CompressiblePotentialApplicationFastSuite) { + Model this_model; + ModelPart& model_part = this_model.CreateModelPart("Main", 3); + + GenerateTestingElement(model_part); + Element::Pointer p_element = model_part.pGetElement(1); + + const std::array& potential{1.0, 733.13764, 929.1948}; + AssignCustomPerturbationPotentialsToElement(*p_element, potential); + const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); + const double pressure_coefficient = + PotentialFlowUtilities::ComputePerturbationCompressiblePressureCoefficient<2, 3>( + *p_element, r_current_process_info); + + const double reference_pressure_coefficient = -3.968253968253968; + const double tolerance = 1e-15; + + KRATOS_ERROR_IF(!(std::abs(pressure_coefficient - reference_pressure_coefficient) < tolerance)) + << "Check failed because pressure_coefficient = " << pressure_coefficient << + " is not near to reference_pressure_coefficient = " << reference_pressure_coefficient << + " within the tolerance " << tolerance << std::endl; +} + // Checks the function ComputePerturbationLocalSpeedOfSound from the utilities KRATOS_TEST_CASE_IN_SUITE(ComputePerturbationLocalSpeedOfSound, CompressiblePotentialApplicationFastSuite) { Model this_model; ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTestingElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPerturbationPotentialsToElement(*pElement); + AssignPerturbationPotentialsToElement(*p_element); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); const double local_speed_of_sound = PotentialFlowUtilities::ComputePerturbationLocalSpeedOfSound<2, 3>( - *pElement, r_current_process_info); + *p_element, r_current_process_info); KRATOS_CHECK_NEAR(local_speed_of_sound, 324.1317633309022, 1e-13); } @@ -320,13 +365,13 @@ KRATOS_TEST_CASE_IN_SUITE(ComputePerturbationLocalMachNumber, CompressiblePotent ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTestingElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - AssignPerturbationPotentialsToElement(*pElement); + AssignPerturbationPotentialsToElement(*p_element); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); const double local_mach_number = PotentialFlowUtilities::ComputePerturbationLocalMachNumber<2, 3>( - *pElement, r_current_process_info); + *p_element, r_current_process_info); KRATOS_CHECK_NEAR(local_mach_number, 0.9474471158469713, 1e-16); } diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_processes.cpp b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_processes.cpp index 8489f8ee0c86..ea4af2435d9e 100644 --- a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_processes.cpp +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_processes.cpp @@ -151,8 +151,8 @@ namespace Kratos { std::vector elemNodes{ 1, 2, 3 }; model_part.CreateNewElement("EmbeddedIncompressiblePotentialFlowElement2D3N", 1, elemNodes, pElemProp); - Element::Pointer pElement = model_part.pGetElement(1); - pElement -> Set(ACTIVE); + Element::Pointer p_element = model_part.pGetElement(1); + p_element -> Set(ACTIVE); // Define the nodal values std::array potential; @@ -167,10 +167,10 @@ namespace Kratos { for (unsigned int i = 0; i < 3; i++) - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = potential[i]; for (unsigned int i = 0; i < 3; i++) - pElement->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = distances[i]; + p_element->GetGeometry()[i].FastGetSolutionStepValue(GEOMETRY_DISTANCE) = distances[i]; Vector resultant_force(3); ComputeEmbeddedLiftProcess<2,3>(model_part, resultant_force).Execute(); @@ -203,7 +203,7 @@ namespace Kratos { model_part.CreateNewProperties(0); Properties::Pointer pElemProp = model_part.pGetProperties(0); std::vector elemNodes{ 1, 2, 3 }; - ModelPart::ElementType::Pointer pElement = model_part.CreateNewElement("IncompressiblePotentialFlowElement2D3N", 1, elemNodes, pElemProp); + ModelPart::ElementType::Pointer p_element = model_part.CreateNewElement("IncompressiblePotentialFlowElement2D3N", 1, elemNodes, pElemProp); // Create body sub_model_part ModelPart& body_model_part = model_part.CreateSubModelPart("body_model_part"); @@ -218,7 +218,7 @@ namespace Kratos { // Execute the Define2DWakeProcess Define2DWakeProcess.ExecuteInitialize(); - const int wake = pElement->GetValue(WAKE); + const int wake = p_element->GetValue(WAKE); KRATOS_CHECK_NEAR(wake, 1, 1e-6); } diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_transonic_perturbation_potential_element.cpp b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_transonic_perturbation_potential_element.cpp index 5d92acc2f01f..6e358d4049f4 100644 --- a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_transonic_perturbation_potential_element.cpp +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_transonic_perturbation_potential_element.cpp @@ -87,16 +87,16 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowElementRHS, Compress ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTransonicPerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - pElement->SetFlags(INLET); + Element::Pointer p_element = model_part.pGetElement(1); + p_element->SetFlags(INLET); - AssignPotentialsToNormalTransonicPerturbationElement(pElement); + AssignPotentialsToNormalTransonicPerturbationElement(p_element); // Compute RHS Vector RHS = ZeroVector(4); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateRightHandSide(RHS, r_current_process_info); + p_element->CalculateRightHandSide(RHS, r_current_process_info); std::vector reference{146.2643261263345,-122.1426284341492,-24.12169769218525}; @@ -111,16 +111,16 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowInletElementRHS, Com ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTransonicPerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->Initialize(r_current_process_info); + p_element->Initialize(r_current_process_info); - AssignPotentialsToNormalTransonicPerturbationElement(pElement); + AssignPotentialsToNormalTransonicPerturbationElement(p_element); // Compute RHS Vector RHS = ZeroVector(3); - pElement->CalculateRightHandSide(RHS, r_current_process_info); + p_element->CalculateRightHandSide(RHS, r_current_process_info); std::vector reference{146.2643261263345,-122.1426284341492,-24.12169769218525}; @@ -135,17 +135,17 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowElementLHS, Compress ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTransonicPerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); - pElement->SetFlags(INLET); + p_element->SetFlags(INLET); - AssignPotentialsToNormalTransonicPerturbationElement(pElement); + AssignPotentialsToNormalTransonicPerturbationElement(p_element); // Compute LHS Matrix LHS = ZeroMatrix(4, 4); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); std::array reference{ 0.061142784644415527,-0.1306215050744058, 0.06947872042999037, 0.0, -0.1306215050744058, 0.6710758508914103,-0.5404543458170046, 0.0, @@ -169,20 +169,20 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicElementLHS GenerateTransonicPerturbationElement(model_part); GenerateTransonicPerturbationUpwindElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); Element::Pointer pUpwindElement = model_part.pGetElement(2); FindNodalNeighboursProcess find_nodal_neighbours_process(model_part); find_nodal_neighbours_process.Execute(); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->Initialize(r_current_process_info); + p_element->Initialize(r_current_process_info); pUpwindElement->SetFlags(INLET); std::array high_potential{1.0, 200.0, 100.0}; // node id order 23 74 55 std::array low_potential{1.0, 100.0, 150.0}; // node id order 23 55 67 // mach number 1.92516 - AssignPerturbationPotentialsToTransonicElement(*pElement, high_potential); + AssignPerturbationPotentialsToTransonicElement(*p_element, high_potential); // mach number 0.39943 AssignPerturbationPotentialsToTransonicElement(*pUpwindElement, low_potential); @@ -191,7 +191,7 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicElementLHS } Element::DofsVectorType CurrentElementalDofList; - pElement->GetDofList(CurrentElementalDofList, r_current_process_info); + p_element->GetDofList(CurrentElementalDofList, r_current_process_info); Element::DofsVectorType UpwindElementalDofList; pUpwindElement->GetDofList(UpwindElementalDofList, r_current_process_info); @@ -206,7 +206,7 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicElementLHS // // Compute LHS Matrix LHS = ZeroMatrix(4, 4); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); std::array reference{ 0.37708651121240516,-0.54915594944726343,0.17743192602659938,-0.0053624877917411414, -0.35664864389216139,1.0308840557120569,-0.68092794767744869,0.0066925358575532206, @@ -230,20 +230,20 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicDecelerati GenerateTransonicPerturbationElement(model_part); GenerateTransonicPerturbationUpwindElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); Element::Pointer pUpwindElement = model_part.pGetElement(2); FindNodalNeighboursProcess find_nodal_neighbours_process(model_part); find_nodal_neighbours_process.Execute(); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->Initialize(r_current_process_info); + p_element->Initialize(r_current_process_info); pUpwindElement->SetFlags(INLET); std::array high_potential{10.0, 200.0, 350.0}; // node id order 23 74 55 std::array higher_potential{10.0, 350.0, 150.0}; // node id order 23 55 67 // mach number 1.92516 - AssignPerturbationPotentialsToTransonicElement(*pElement, high_potential); + AssignPerturbationPotentialsToTransonicElement(*p_element, high_potential); // mach number 2.0898 AssignPerturbationPotentialsToTransonicElement(*pUpwindElement, higher_potential); @@ -253,7 +253,7 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicDecelerati } Element::DofsVectorType CurrentElementalDofList; - pElement->GetDofList(CurrentElementalDofList, r_current_process_info); + p_element->GetDofList(CurrentElementalDofList, r_current_process_info); Element::DofsVectorType UpwindElementalDofList; pUpwindElement->GetDofList(UpwindElementalDofList, r_current_process_info); @@ -268,7 +268,7 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicDecelerati // // Compute LHS Matrix LHS = ZeroMatrix(4, 4); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); std::array reference{ -0.054669771246690091,-0.14888540383260493,0.40255671949894734,-0.19900154441965234, -0.083557300280464597,0.51822478070562072,-0.55794161182804491,0.12327413140288881, @@ -292,7 +292,7 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicElementRHS GenerateTransonicPerturbationElement(model_part); GenerateTransonicPerturbationUpwindElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); Element::Pointer pUpwindElement = model_part.pGetElement(2); FindNodalNeighboursProcess find_nodal_neighbours_process(model_part); @@ -301,7 +301,7 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicElementRHS std::array high_potential{1.0, 200.0, 100.0}; // node id order 23 74 55 std::array low_potential{1.0, 100.0, 150.0}; // node id order 23 55 67 // mach number 1.92516 - AssignPerturbationPotentialsToTransonicElement(*pElement, high_potential); + AssignPerturbationPotentialsToTransonicElement(*p_element, high_potential); // mach number 0.3999 AssignPerturbationPotentialsToTransonicElement(*pUpwindElement, low_potential); @@ -312,7 +312,7 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicElementRHS Element::DofsVectorType CurrentElementalDofList; const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->GetDofList(CurrentElementalDofList, r_current_process_info); + p_element->GetDofList(CurrentElementalDofList, r_current_process_info); Element::DofsVectorType UpwindElementalDofList; pUpwindElement->GetDofList(UpwindElementalDofList, r_current_process_info); @@ -324,13 +324,13 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowSupersonicElementRHS UpwindElementalDofList[i]->SetEquationId(upwind_ids[i]); } - pElement->Initialize(r_current_process_info); + p_element->Initialize(r_current_process_info); pUpwindElement->SetFlags(INLET); // Compute RHS Vector RHS = ZeroVector(4); - pElement->CalculateRightHandSide(RHS, r_current_process_info); + p_element->CalculateRightHandSide(RHS, r_current_process_info); std::vector reference{185.25633340652948,-231.20512387394589,45.948790467416408,0.0}; @@ -345,18 +345,18 @@ KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowInletElementLHS, Com ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTransonicPerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->Initialize(r_current_process_info); + p_element->Initialize(r_current_process_info); - pElement->SetFlags(INLET); + p_element->SetFlags(INLET); - AssignPotentialsToNormalTransonicPerturbationElement(pElement); + AssignPotentialsToNormalTransonicPerturbationElement(p_element); // Compute LHS Matrix LHS = ZeroMatrix(4, 4); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); std::array reference{ 0.061142784644415527,-0.1306215050744058, 0.06947872042999037, -0.1306215050744058, 0.67107585089141042,-0.5404543458170046, @@ -377,12 +377,12 @@ KRATOS_TEST_CASE_IN_SUITE(PingTransonicPerturbationPotentialFlowElementLHS, Comp ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTransonicPerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); - const unsigned int number_of_nodes = pElement->GetGeometry().size(); + Element::Pointer p_element = model_part.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); - pElement->SetFlags(INLET); + p_element->SetFlags(INLET); - AssignPotentialsToNormalTransonicPerturbationElement(pElement); + AssignPotentialsToNormalTransonicPerturbationElement(p_element); Vector RHS_original = ZeroVector(number_of_nodes); Matrix LHS_original = ZeroMatrix(number_of_nodes, number_of_nodes); @@ -391,17 +391,17 @@ KRATOS_TEST_CASE_IN_SUITE(PingTransonicPerturbationPotentialFlowElementLHS, Comp // Compute original RHS and LHS const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); + p_element->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); double delta = 1e-3; for(unsigned int i = 0; i < number_of_nodes; i++){ // Pinging - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; Vector RHS_pinged = ZeroVector(number_of_nodes); Matrix LHS_pinged = ZeroMatrix(number_of_nodes, number_of_nodes); // Compute pinged LHS and RHS - pElement->CalculateLocalSystem(LHS_pinged, RHS_pinged, r_current_process_info); + p_element->CalculateLocalSystem(LHS_pinged, RHS_pinged, r_current_process_info); for(unsigned int k = 0; k < number_of_nodes; k++){ // Compute the finite difference estimate of the sensitivity @@ -411,14 +411,10 @@ KRATOS_TEST_CASE_IN_SUITE(PingTransonicPerturbationPotentialFlowElementLHS, Comp } // Unpinging - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; } - for (unsigned int i = 0; i < LHS_finite_diference.size1(); i++) { - for (unsigned int j = 0; j < LHS_finite_diference.size2(); j++) { - KRATOS_CHECK_NEAR(LHS_finite_diference(i,j), LHS_analytical(i,j), 1e-10); - } - } + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); } /** Checks the TransonicPerturbationPotentialFlowElement. @@ -431,21 +427,21 @@ KRATOS_TEST_CASE_IN_SUITE(PingTransonicPerturbationPotentialFlowSupersonicElemen GenerateTransonicPerturbationElement(model_part); GenerateTransonicPerturbationUpwindElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); Element::Pointer pUpwindElement = model_part.pGetElement(2); - const unsigned int number_of_nodes = pElement->GetGeometry().size(); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); FindNodalNeighboursProcess find_nodal_neighbours_process(model_part); find_nodal_neighbours_process.Execute(); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->Initialize(r_current_process_info); + p_element->Initialize(r_current_process_info); pUpwindElement->SetFlags(INLET); std::array high_potential{1.0, 200.0, 100.0}; // node id order 23 74 55 std::array low_potential{1.0, 100.0, 150.0}; // node id order 23 55 67 // mach number 1.92516 - AssignPerturbationPotentialsToTransonicElement(*pElement, high_potential); + AssignPerturbationPotentialsToTransonicElement(*p_element, high_potential); // mach number 0.39943 AssignPerturbationPotentialsToTransonicElement(*pUpwindElement, low_potential); @@ -454,7 +450,7 @@ KRATOS_TEST_CASE_IN_SUITE(PingTransonicPerturbationPotentialFlowSupersonicElemen } Element::DofsVectorType CurrentElementalDofList; - pElement->GetDofList(CurrentElementalDofList, r_current_process_info); + p_element->GetDofList(CurrentElementalDofList, r_current_process_info); Element::DofsVectorType UpwindElementalDofList; pUpwindElement->GetDofList(UpwindElementalDofList, r_current_process_info); @@ -472,13 +468,13 @@ KRATOS_TEST_CASE_IN_SUITE(PingTransonicPerturbationPotentialFlowSupersonicElemen Matrix LHS_analytical = ZeroMatrix(number_of_nodes + 1, number_of_nodes + 1); // Compute original RHS and LHS - pElement->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); + p_element->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); double delta = 1e-3; for(unsigned int i = 0; i < 4; i++){ // Pinging if (i < 3) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; } else { pUpwindElement->GetGeometry()[2].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; @@ -487,7 +483,7 @@ KRATOS_TEST_CASE_IN_SUITE(PingTransonicPerturbationPotentialFlowSupersonicElemen Vector RHS_pinged = ZeroVector(number_of_nodes + 1); Matrix LHS_pinged = ZeroMatrix(number_of_nodes + 1, number_of_nodes + 1); // Compute pinged LHS and RHS - pElement->CalculateLocalSystem(LHS_pinged, RHS_pinged, r_current_process_info); + p_element->CalculateLocalSystem(LHS_pinged, RHS_pinged, r_current_process_info); for(unsigned int k = 0; k < number_of_nodes + 1; k++){ // Compute the finite difference estimate of the sensitivity @@ -498,18 +494,14 @@ KRATOS_TEST_CASE_IN_SUITE(PingTransonicPerturbationPotentialFlowSupersonicElemen // Unpinging if (i < 3) { - pElement->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; } else { pUpwindElement->GetGeometry()[2].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; } } - for (unsigned int i = 0; i < LHS_finite_diference.size1(); i++) { - for (unsigned int j = 0; j < LHS_finite_diference.size2(); j++) { - KRATOS_CHECK_NEAR(LHS_finite_diference(i,j), LHS_analytical(i,j), 1e-10); - } - } + KRATOS_CHECK_MATRIX_NEAR(LHS_finite_diference, LHS_analytical, 1e-10); } KRATOS_TEST_CASE_IN_SUITE(TransonicPerturbationPotentialFlowElementEquationId, CompressiblePotentialApplicationFastSuite) { @@ -586,21 +578,21 @@ KRATOS_TEST_CASE_IN_SUITE(WakeTransonicPerturbationPotentialFlowElementRHS, Comp ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTransonicPerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); BoundedVector distances = AssignDistancesToPerturbationTransonicElement(); - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; const std::array potential{1.0, 101.0, 150.0, 6.0, 105.0, 155.0}; - AssignPotentialsToWakeTransonicPerturbationElement(pElement, distances, potential); + AssignPotentialsToWakeTransonicPerturbationElement(p_element, distances, potential); // Compute RHS and LHS Vector RHS = ZeroVector(6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateRightHandSide(RHS, r_current_process_info); + p_element->CalculateRightHandSide(RHS, r_current_process_info); std::vector reference{146.392649744264,-0.9625396130203431,0.4812698065101715,-0.4812698065101715,-121.8478896122452,-24.06349032550858}; @@ -612,21 +604,21 @@ KRATOS_TEST_CASE_IN_SUITE(WakeTransonicPerturbationPotentialFlowElementLHS, Comp ModelPart& model_part = this_model.CreateModelPart("Main", 3); GenerateTransonicPerturbationElement(model_part); - Element::Pointer pElement = model_part.pGetElement(1); + Element::Pointer p_element = model_part.pGetElement(1); BoundedVector distances = AssignDistancesToPerturbationTransonicElement(); - pElement->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; - pElement->GetValue(WAKE) = true; + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; const std::array potential{1.0, 100.0, 150.0, 6.0, 105.0, 155.0}; - AssignPotentialsToWakeTransonicPerturbationElement(pElement, distances, potential); + AssignPotentialsToWakeTransonicPerturbationElement(p_element, distances, potential); // Compute LHS Matrix LHS = ZeroMatrix(6, 6); const ProcessInfo& r_current_process_info = model_part.GetProcessInfo(); - pElement->CalculateLeftHandSide(LHS, r_current_process_info); + p_element->CalculateLeftHandSide(LHS, r_current_process_info); // Check the LHS values std::array reference{0.061142784644415527,-0.1306215050744058,0.06947872042999037,0,0,0, diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_utilities.cpp b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_utilities.cpp new file mode 100644 index 000000000000..8c7337ba4b88 --- /dev/null +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_utilities.cpp @@ -0,0 +1,172 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Inigo Lopez and Marc Núñez +// + + +#include "tests/cpp_tests/test_utilities.h" +#include "includes/model_part.h" +#include "compressible_potential_flow_application_variables.h" + +namespace Kratos { +namespace PotentialFlowTestUtilities { + +template +void AssignPotentialsToNormalElement(Element& rElement, const std::array rPotential) +{ + for (unsigned int i = 0; i < NumNodes; i++) + rElement.GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i]; +} + +template +void AssignPotentialsToWakeElement(Element& rElement, const array_1d& rDistances, const std::array& rPotential) +{ + for (unsigned int i = 0; i < NumNodes; i++){ + if (rDistances(i) > 0.0) + rElement.GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i]; + else + rElement.GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = rPotential[i]; + } + for (unsigned int i = 0; i < NumNodes; i++){ + if (rDistances(i) < 0.0) + rElement.GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) = rPotential[i+NumNodes]; + else + rElement.GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) = rPotential[i+NumNodes]; + } +} + +template +BoundedVector AssignDistancesToElement() +{ + BoundedVector distances; + for(unsigned int i = 0; i < NumNodes; i++){ + if(i < 1){ + distances(i) = 1.0; + } + else{ + distances(i) = -1.0; + } + } + return distances; +} + +void ComputeElementalSensitivitiesMatrixRow(ModelPart& rModelPart, double delta, unsigned int row, Matrix& rLHS_original, Vector& rRHS_original, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical){ + Element::Pointer p_element = rModelPart.pGetElement(1); + const unsigned int number_of_nodes = p_element->GetGeometry().size(); + + // Compute pinged LHS and RHS + Vector RHS_pinged = ZeroVector(number_of_nodes); + Matrix LHS_pinged = ZeroMatrix(number_of_nodes, number_of_nodes); + const ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo(); + p_element->CalculateLocalSystem(LHS_pinged, RHS_pinged, r_current_process_info); + + for(unsigned int k = 0; k < rLHS_original.size2(); k++){ + // Compute the finite difference estimate of the sensitivity + rLHS_finite_diference( k, row) = -(RHS_pinged(k)-rRHS_original(k)) / delta; + // Compute the average of the original and pinged analytic sensitivities + rLHS_analytical( k, row) = 0.5 * (rLHS_original(k,row) + LHS_pinged(k,row)); + } +} + +template +void ComputeElementalSensitivities(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential){ + Element::Pointer p_element = rModelPart.pGetElement(1); + + AssignPotentialsToNormalElement(*p_element, rPotential); + + // Compute original RHS and LHS + Vector RHS_original = ZeroVector(NumNodes); + Matrix LHS_original = ZeroMatrix(NumNodes, NumNodes); + const ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo(); + p_element->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); + + double delta = 1e-3; + for(unsigned int i = 0; i < NumNodes; i++){ + // Pinging + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; + + ComputeElementalSensitivitiesMatrixRow(rModelPart, delta, i, LHS_original, RHS_original, rLHS_finite_diference, rLHS_analytical); + + // Unpinging + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; + } +} + +template +void ComputeWakeElementalSensitivities(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential){ + Element::Pointer p_element = rModelPart.pGetElement(1); + + BoundedVector distances = AssignDistancesToElement(); + p_element->GetValue(WAKE_ELEMENTAL_DISTANCES) = distances; + p_element->GetValue(WAKE) = true; + + AssignPotentialsToWakeElement(*p_element, distances, rPotential); + + // Compute original RHS and LHS + Vector RHS_original = ZeroVector(2*NumNodes); + Matrix LHS_original = ZeroMatrix(2*NumNodes, 2*NumNodes); + const ProcessInfo& r_current_process_info = rModelPart.GetProcessInfo(); + p_element->CalculateLocalSystem(LHS_original, RHS_original, r_current_process_info); + + double delta = 1e-3; + for(unsigned int i = 0; i < 2*NumNodes; i++){ + if(i < NumNodes){ + // Pinging + if (distances(i) > 0.0) + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; + else + p_element->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) += delta; + + ComputeElementalSensitivitiesMatrixRow(rModelPart, delta, i, LHS_original, RHS_original, rLHS_finite_diference, rLHS_analytical); + + // Unpinging + if (distances(i) > 0.0) + p_element->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; + else + p_element->GetGeometry()[i].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) -= delta; + } + else{ + // Pinging + if (distances(i-NumNodes) > 0.0) + p_element->GetGeometry()[i-NumNodes].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) += delta; + else + p_element->GetGeometry()[i-NumNodes].FastGetSolutionStepValue(VELOCITY_POTENTIAL) += delta; + + ComputeElementalSensitivitiesMatrixRow(rModelPart, delta, i, LHS_original, RHS_original, rLHS_finite_diference, rLHS_analytical); + + // Unpinging + if (distances(i-NumNodes) > 0.0) + p_element->GetGeometry()[i-NumNodes].FastGetSolutionStepValue(AUXILIARY_VELOCITY_POTENTIAL) -= delta; + else + p_element->GetGeometry()[i-NumNodes].FastGetSolutionStepValue(VELOCITY_POTENTIAL) -= delta; + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Template instantiation + +// 2D +template void AssignPotentialsToNormalElement<3>(Element& rElement, const std::array rPotential); +template void AssignPotentialsToWakeElement<3>(Element& rElement, const array_1d& rDistances, const std::array& rPotential); +template BoundedVector AssignDistancesToElement<3>(); +template void ComputeElementalSensitivities<3>(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential); +template void ComputeWakeElementalSensitivities<3>(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential); + +// 3D +template void AssignPotentialsToNormalElement<4>(Element& rElement, const std::array rPotential); +template void AssignPotentialsToWakeElement<4>(Element& rElement, const array_1d& rDistances, const std::array& rPotential); +template BoundedVector AssignDistancesToElement<4>(); +template void ComputeElementalSensitivities<4>(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential); +template void ComputeWakeElementalSensitivities<4>(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential); + + +} // namespace PotentialFlowTestUtilities +} // namespace Kratos diff --git a/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_utilities.h b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_utilities.h new file mode 100644 index 000000000000..53db0135cbaa --- /dev/null +++ b/applications/CompressiblePotentialFlowApplication/tests/cpp_tests/test_utilities.h @@ -0,0 +1,43 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Inigo Lopez and Marc Núñez +// + +#include "containers/array_1d.h" +#include "includes/ublas_interface.h" + +namespace Kratos +{ + // forward-declaring + class ModelPart; + class Element; + +namespace PotentialFlowTestUtilities +{ + +template +void AssignPotentialsToNormalElement(Element& rElement, const std::array rPotential); + +template +void AssignPotentialsToWakeElement(Element& rElement, const array_1d& rDistances, const std::array& rPotential); + +template +BoundedVector AssignDistancesToElement(); + +void ComputeElementalSensitivitiesMatrixRow(ModelPart& rModelPart, double delta, unsigned int row, Matrix& rLHS_original, Vector& rRHS_original, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical); + +template +void ComputeElementalSensitivities(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential); + +template +void ComputeWakeElementalSensitivities(ModelPart& rModelPart, Matrix& rLHS_finite_diference, Matrix& rLHS_analytical, const std::array rPotential); + +} // namespace PotentialFlowTestUtilities +} // namespace Kratos \ No newline at end of file diff --git a/applications/CompressiblePotentialFlowApplication/tests/potential_flow_test_factory.py b/applications/CompressiblePotentialFlowApplication/tests/potential_flow_test_factory.py index 6f54982cb30f..eca5d72ce310 100644 --- a/applications/CompressiblePotentialFlowApplication/tests/potential_flow_test_factory.py +++ b/applications/CompressiblePotentialFlowApplication/tests/potential_flow_test_factory.py @@ -70,6 +70,7 @@ def test_Naca0012SmallCompressible(self): self._check_results(self.main_model_part.ProcessInfo[CPFApp.MOMENT_COEFFICIENT], -0.1631792300021498, 0.0, 1e-9) self._check_results(self.main_model_part.ProcessInfo[CPFApp.LIFT_COEFFICIENT_JUMP], 0.4876931961465126, 0.0, 1e-9) self._check_results(self.main_model_part.ProcessInfo[CPFApp.LIFT_COEFFICIENT_FAR_FIELD], 0.4953997676243705, 0.0, 1e-9) + self._check_perimeter_computation() for file_name in os.listdir(): if file_name.endswith(".time"): @@ -301,5 +302,11 @@ def _check_results(self, result, reference, rel_tol, abs_tol): self.assertTrue(isclosethis, msg=full_msg) + def _check_perimeter_computation(self): + body_model_part = self.main_model_part.GetSubModelPart("Body2D_Body") + perimeter1 = sum([cond.GetGeometry().Area() for cond in body_model_part.Conditions]) + perimeter2 = CPFApp.PotentialFlowUtilities.CalculateArea(body_model_part.Conditions) + self._check_results(perimeter1, perimeter2, 1e-9, 1e-9) + if __name__ == '__main__': UnitTest.main() diff --git a/applications/ConstitutiveLawsApplication/CMakeLists.txt b/applications/ConstitutiveLawsApplication/CMakeLists.txt index 958a99c78b60..b2921319d32c 100644 --- a/applications/ConstitutiveLawsApplication/CMakeLists.txt +++ b/applications/ConstitutiveLawsApplication/CMakeLists.txt @@ -36,6 +36,12 @@ pybind11_add_module(KratosConstitutiveLawsApplication MODULE THIN_LTO ${KRATOS_C target_link_libraries(KratosConstitutiveLawsApplication PRIVATE KratosConstitutiveLawsCore) set_target_properties(KratosConstitutiveLawsApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosConstitutiveLawsCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosConstitutiveLawsApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosConstitutiveLawsApplication PROPERTIES SUFFIX .pyd) @@ -46,12 +52,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosConstitutiveLawsApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosConstitutiveLawsCore) - cotire(KratosConstitutiveLawsApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/ConstitutiveLawsApplication.py KratosMultiphysics/ConstitutiveLawsApplication/__init__.py ) diff --git a/applications/ConstitutiveLawsApplication/constitutive_laws_application.cpp b/applications/ConstitutiveLawsApplication/constitutive_laws_application.cpp index ae30ba8c7957..285f7ae88c40 100644 --- a/applications/ConstitutiveLawsApplication/constitutive_laws_application.cpp +++ b/applications/ConstitutiveLawsApplication/constitutive_laws_application.cpp @@ -443,5 +443,25 @@ void KratosConstitutiveLawsApplication::Register() KRATOS_REGISTER_CONSTITUTIVE_LAW("ParallelRuleOfMixturesLaw2D", mParallelRuleOfMixturesLaw2D); KRATOS_REGISTER_CONSTITUTIVE_LAW("ParallelRuleOfMixturesLaw3D", mParallelRuleOfMixturesLaw3D); + // Constitutive laws variables + + //Faituge variables + KRATOS_REGISTER_VARIABLE(HIGH_CYCLE_FATIGUE_COEFFICIENTS) + KRATOS_REGISTER_VARIABLE(FATIGUE_REDUCTION_FACTOR) + KRATOS_REGISTER_VARIABLE(NUMBER_OF_CYCLES) + KRATOS_REGISTER_VARIABLE(LOCAL_NUMBER_OF_CYCLES) + KRATOS_REGISTER_VARIABLE(WOHLER_STRESS) + KRATOS_REGISTER_VARIABLE(REVERSION_FACTOR_RELATIVE_ERROR) + KRATOS_REGISTER_VARIABLE(MAX_STRESS_RELATIVE_ERROR) + KRATOS_REGISTER_VARIABLE(MAX_STRESS) + KRATOS_REGISTER_VARIABLE(THRESHOLD_STRESS) + KRATOS_REGISTER_VARIABLE(CYCLE_INDICATOR) + KRATOS_REGISTER_VARIABLE(CYCLES_TO_FAILURE) + KRATOS_REGISTER_VARIABLE(TIME_INCREMENT) + KRATOS_REGISTER_VARIABLE(DAMAGE_ACTIVATION) + KRATOS_REGISTER_VARIABLE(PREVIOUS_CYCLE); + KRATOS_REGISTER_VARIABLE(CYCLE_PERIOD) + KRATOS_REGISTER_VARIABLE(ADVANCE_STRATEGY_APPLIED); + } } // namespace Kratos. diff --git a/applications/ConstitutiveLawsApplication/constitutive_laws_application_variables.cpp b/applications/ConstitutiveLawsApplication/constitutive_laws_application_variables.cpp index 437aa91cd34e..2594262a5a35 100644 --- a/applications/ConstitutiveLawsApplication/constitutive_laws_application_variables.cpp +++ b/applications/ConstitutiveLawsApplication/constitutive_laws_application_variables.cpp @@ -15,5 +15,22 @@ namespace Kratos { +// Constitutive laws variables +KRATOS_CREATE_VARIABLE(Vector, HIGH_CYCLE_FATIGUE_COEFFICIENTS) +KRATOS_CREATE_VARIABLE(double, FATIGUE_REDUCTION_FACTOR) +KRATOS_CREATE_VARIABLE(int, NUMBER_OF_CYCLES) +KRATOS_CREATE_VARIABLE(int, LOCAL_NUMBER_OF_CYCLES) +KRATOS_CREATE_VARIABLE(double, WOHLER_STRESS) +KRATOS_CREATE_VARIABLE(double, REVERSION_FACTOR_RELATIVE_ERROR) +KRATOS_CREATE_VARIABLE(double, MAX_STRESS_RELATIVE_ERROR) +KRATOS_CREATE_VARIABLE(double, MAX_STRESS) +KRATOS_CREATE_VARIABLE(double, THRESHOLD_STRESS) +KRATOS_CREATE_VARIABLE(bool, CYCLE_INDICATOR) +KRATOS_CREATE_VARIABLE(double, CYCLES_TO_FAILURE) +KRATOS_CREATE_VARIABLE(double, TIME_INCREMENT) +KRATOS_CREATE_VARIABLE(bool, DAMAGE_ACTIVATION) +KRATOS_CREATE_VARIABLE(double, PREVIOUS_CYCLE); +KRATOS_CREATE_VARIABLE(double, CYCLE_PERIOD) +KRATOS_CREATE_VARIABLE(bool, ADVANCE_STRATEGY_APPLIED); } diff --git a/applications/ConstitutiveLawsApplication/constitutive_laws_application_variables.h b/applications/ConstitutiveLawsApplication/constitutive_laws_application_variables.h index d4aa53fd43a0..8be6e0f0e94a 100644 --- a/applications/ConstitutiveLawsApplication/constitutive_laws_application_variables.h +++ b/applications/ConstitutiveLawsApplication/constitutive_laws_application_variables.h @@ -11,7 +11,7 @@ // Riccardo Rossi // -#if !defined(KRATOS_CONSTITUTIVE_LAWS_APPLICATION_VARIABLES_H_INCLUDED ) +#if !defined(KRATOS_CONSTITUTIVE_LAWS_APPLICATION_VARIABLES_H_INCLUDED) #define KRATOS_CONSTITUTIVE_LAWS_APPLICATION_VARIABLES_H_INCLUDED // System includes @@ -20,9 +20,29 @@ // Project includes #include "includes/define.h" +#include "includes/mat_variables.h" namespace Kratos { +///@name Functions +///@{ + // Constitutive laws variables + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, Vector, HIGH_CYCLE_FATIGUE_COEFFICIENTS) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, FATIGUE_REDUCTION_FACTOR) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, int, NUMBER_OF_CYCLES) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, int, LOCAL_NUMBER_OF_CYCLES) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, WOHLER_STRESS) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, REVERSION_FACTOR_RELATIVE_ERROR) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, MAX_STRESS_RELATIVE_ERROR) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, MAX_STRESS) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, THRESHOLD_STRESS) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, bool, CYCLE_INDICATOR) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, CYCLES_TO_FAILURE) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, TIME_INCREMENT) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, bool, DAMAGE_ACTIVATION) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, PREVIOUS_CYCLE); + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, double, CYCLE_PERIOD) + KRATOS_DEFINE_APPLICATION_VARIABLE(CONSTITUTIVE_LAWS_APPLICATION, bool, ADVANCE_STRATEGY_APPLIED); } diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_kinematic_plasticity.h b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_kinematic_plasticity.h index 4c224bc2d650..79f2924beb60 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_kinematic_plasticity.h +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_kinematic_plasticity.h @@ -21,6 +21,7 @@ #include "utilities/math_utils.h" #include "custom_utilities/constitutive_law_utilities.h" #include "structural_mechanics_application_variables.h" +#include "generic_constitutive_law_integrator_plasticity.h" namespace Kratos { @@ -199,30 +200,23 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity while (is_converged == false && iteration <= max_iter) { threshold_indicator = rUniaxialStress - rThreshold; plastic_consistency_factor_increment = threshold_indicator * rPlasticDenominator; - noalias(rPlasticStrainIncrement) = plastic_consistency_factor_increment * rDerivativePlasticPotential; noalias(rPlasticStrain) += rPlasticStrainIncrement; noalias(delta_sigma) = prod(rConstitutiveMatrix, rPlasticStrainIncrement); noalias(rPredictiveStressVector) -= delta_sigma; - CalculateBackStress(rPredictiveStressVector, rValues, rPreviousStressVector, rPlasticStrainIncrement, rBackStressVector); - noalias(kin_hard_stress_vector) = rPredictiveStressVector - rBackStressVector; threshold_indicator = CalculatePlasticParameters(kin_hard_stress_vector, rStrainVector, rUniaxialStress, rThreshold, rPlasticDenominator, rYieldSurfaceDerivative, rDerivativePlasticPotential, rPlasticDissipation, rPlasticStrainIncrement, rConstitutiveMatrix, rValues, CharacteristicLength, rPlasticStrain, rBackStressVector); - if (std::abs(threshold_indicator) <= std::abs(1.0e-4 * rThreshold)) { // Has converged is_converged = true; } else { iteration++; } } - - if (iteration > max_iter) { - KRATOS_WARNING_FIRST_N("Backward Euler Plasticity", 20) << "Maximum number of iterations in plasticity loop reached..." << std::endl; - } + KRATOS_WARNING_IF("GenericConstitutiveLawIntegratorKinematicPlasticity", iteration > max_iter) << "Maximum number of iterations in plasticity loop reached..." << std::endl; } /** @@ -388,41 +382,8 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity double& rCompressionIndicatorFactor ) { - // We do an initial check - if (norm_2(rPredictiveStressVector) < 1.0e-8) { - rTensileIndicatorFactor = 0.5; - rCompressionIndicatorFactor = 0.5; - return; - } - - // We proceed as usual - array_1d principal_stresses = ZeroVector(Dimension); - ConstitutiveLawUtilities::CalculatePrincipalStresses(principal_stresses, rPredictiveStressVector); - - double suma = 0.0, sumb = 0.0, sumc = 0.0; - double aux_sa; - - for (IndexType i = 0; i < Dimension; ++i) { - aux_sa = std::abs(principal_stresses[i]); - suma += aux_sa; - sumb += 0.5 * (principal_stresses[i] + aux_sa); - sumc += 0.5 * (-principal_stresses[i] + aux_sa); - } - - if (std::abs(suma) > tolerance) { - rTensileIndicatorFactor = sumb / suma; - rCompressionIndicatorFactor = sumc / suma; - } else { - rTensileIndicatorFactor = sumb; - rCompressionIndicatorFactor = sumc; - } - - // Final check - if ((std::abs(rTensileIndicatorFactor) + std::abs(rCompressionIndicatorFactor)) < tolerance) { - rTensileIndicatorFactor = 0.5; - rCompressionIndicatorFactor = 0.5; - return; - } + GenericConstitutiveLawIntegratorPlasticity::CalculateIndicatorsFactors( + rPredictiveStressVector,rTensileIndicatorFactor,rCompressionIndicatorFactor); } /** @@ -447,45 +408,9 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity const double CharacteristicLength ) { - const Properties& r_material_properties = rValues.GetMaterialProperties(); - - const double young_modulus = r_material_properties[YOUNG_MODULUS]; - const bool has_symmetric_yield_stress = r_material_properties.Has(YIELD_STRESS); - const double yield_compression = has_symmetric_yield_stress ? r_material_properties[YIELD_STRESS] : r_material_properties[YIELD_STRESS_COMPRESSION]; - const double yield_tension = has_symmetric_yield_stress ? r_material_properties[YIELD_STRESS] : r_material_properties[YIELD_STRESS_TENSION]; - const double n = yield_compression / yield_tension; - const double fracture_energy_tension = r_material_properties[FRACTURE_ENERGY]; // Frac energy in tension - const double fracture_energy_comprression = r_material_properties[FRACTURE_ENERGY] * std::pow(n, 2); // Frac energy in compression - - const double characteristic_fracture_energy_tension = fracture_energy_tension / CharacteristicLength; - const double characteristic_fracture_energy_compression = fracture_energy_comprression / CharacteristicLength; - - const double hlim = 2.0 * young_modulus * characteristic_fracture_energy_compression / (std::pow(yield_compression, 2)); - KRATOS_ERROR_IF(CharacteristicLength > hlim) << "The Fracture Energy is to low: " << characteristic_fracture_energy_compression << std::endl; - - double constant0 = 0.0, constant1 = 0.0, dplastic_dissipation = 0.0; - if (characteristic_fracture_energy_tension > 0.000001) { - constant0 = TensileIndicatorFactor / characteristic_fracture_energy_tension; - constant1 = CompressionIndicatorFactor / characteristic_fracture_energy_compression; - } - const double constant = constant0 + constant1; - - for (IndexType i = 0; i < VoigtSize; ++i) { - rHCapa[i] = constant * rPredictiveStressVector[i]; - dplastic_dissipation += rHCapa[i] * PlasticStrainInc[i]; - } - - if (dplastic_dissipation < 0.0 || dplastic_dissipation > 1.0) - dplastic_dissipation = 0.0; - - rPlasticDissipation += dplastic_dissipation; - if (rPlasticDissipation >= 1.0) - rPlasticDissipation = 0.9999; - else if (rPlasticDissipation < 0.0) - rPlasticDissipation = 0.0; - - // We add a check - KRATOS_DEBUG_ERROR_IF(std::isnan(rPlasticDissipation)) << "rPlasticDissipation is nan" << std::endl; + GenericConstitutiveLawIntegratorPlasticity::CalculatePlasticDissipation( + rPredictiveStressVector,TensileIndicatorFactor,CompressionIndicatorFactor, + PlasticStrainInc,rPlasticDissipation,rHCapa,rValues,CharacteristicLength); } /** @@ -510,59 +435,9 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity const double CharacteristicLength ) { - const Properties& r_material_properties = rValues.GetMaterialProperties(); - const int curve_type = r_material_properties[HARDENING_CURVE]; - BoundedVector slopes, eq_thresholds; - - for (IndexType i = 0; i < 2; ++i) { // i:0 Tension ; i:1 compression - switch (static_cast(curve_type)) - { - case HardeningCurveType::LinearSoftening: - CalculateEquivalentStressThresholdHardeningCurveLinearSoftening( - PlasticDissipation, TensileIndicatorFactor, - CompressionIndicatorFactor, eq_thresholds[i], slopes[i], - rValues); - break; - - case HardeningCurveType::ExponentialSoftening: - CalculateEquivalentStressThresholdHardeningCurveExponentialSoftening( - PlasticDissipation, TensileIndicatorFactor, - CompressionIndicatorFactor, eq_thresholds[i], slopes[i], - rValues); - break; - - case HardeningCurveType::InitialHardeningExponentialSoftening: - CalculateEquivalentStressThresholdHardeningCurveInitialHardeningExponentialSoftening( - PlasticDissipation, TensileIndicatorFactor, - CompressionIndicatorFactor, eq_thresholds[i], slopes[i], - rValues); - break; - - case HardeningCurveType::PerfectPlasticity: - CalculateEquivalentStressThresholdHardeningCurvePerfectPlasticity( - PlasticDissipation, TensileIndicatorFactor, - CompressionIndicatorFactor, eq_thresholds[i], slopes[i], - rValues); - break; - - case HardeningCurveType::CurveFittingHardening: // Only for VonMises + Tresca! - CalculateEquivalentStressThresholdCurveFittingHardening( - PlasticDissipation, TensileIndicatorFactor, - CompressionIndicatorFactor, eq_thresholds[i], slopes[i], - rValues, EquivalentPlasticStrain, CharacteristicLength); - break; - - // Add more cases... - - default: - KRATOS_ERROR << " The HARDENING_CURVE of plasticity is not set or wrong..." << curve_type << std::endl; - break; - } - } - - rEquivalentStressThreshold = TensileIndicatorFactor * eq_thresholds[0] + CompressionIndicatorFactor * eq_thresholds[1]; - rSlope = rEquivalentStressThreshold * ((TensileIndicatorFactor * slopes[0] / eq_thresholds[0]) + (CompressionIndicatorFactor * slopes[1] / eq_thresholds[1])); - KRATOS_DEBUG_ERROR_IF(rEquivalentStressThreshold < tolerance) << "Threshold set to zero. TensileIndicatorFactor: " << TensileIndicatorFactor << " eq_thresholds[0]: " << eq_thresholds[0] << " CompressionIndicatorFactor: " << CompressionIndicatorFactor << " eq_thresholds[1]:" << eq_thresholds[1] << std::endl; + GenericConstitutiveLawIntegratorPlasticity::CalculateEquivalentStressThreshold( + PlasticDissipation,TensileIndicatorFactor,CompressionIndicatorFactor,rEquivalentStressThreshold, + rSlope,rValues,EquivalentPlasticStrain,CharacteristicLength); } /** @@ -583,11 +458,8 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity ConstitutiveLaw::Parameters& rValues ) { - double initial_threshold; - GetInitialUniaxialThreshold(rValues, initial_threshold); - - rEquivalentStressThreshold = initial_threshold * std::sqrt(1.0 - PlasticDissipation); - rSlope = -0.5 * (std::pow(initial_threshold, 2.0) / (rEquivalentStressThreshold)); + GenericConstitutiveLawIntegratorPlasticity::CalculateEquivalentStressThresholdHardeningCurveLinearSoftening( + PlasticDissipation,TensileIndicatorFactor,CompressionIndicatorFactor,rEquivalentStressThreshold,rSlope,rValues); } /** @@ -605,14 +477,12 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity const double CompressionIndicatorFactor, double& rEquivalentStressThreshold, double& rSlope, - ConstitutiveLaw::Parameters& rValues + ConstitutiveLaw::Parameters& rValues, + const double CharacteristicLength ) { - double initial_threshold; - GetInitialUniaxialThreshold(rValues, initial_threshold); - - rEquivalentStressThreshold = initial_threshold * (1.0 - PlasticDissipation); - rSlope = - initial_threshold; + GenericConstitutiveLawIntegratorPlasticity::CalculateEquivalentStressThresholdHardeningCurveExponentialSoftening( + PlasticDissipation,TensileIndicatorFactor,CompressionIndicatorFactor,rEquivalentStressThreshold,rSlope,rValues,CharacteristicLength); } /** @@ -633,25 +503,8 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity ConstitutiveLaw::Parameters& rValues ) { - const Properties& r_material_properties = rValues.GetMaterialProperties(); - - double initial_threshold; - GetInitialUniaxialThreshold(rValues, initial_threshold); - const double ultimate_stress = r_material_properties[MAXIMUM_STRESS]; // sikpi - const double max_stress_position = r_material_properties[MAXIMUM_STRESS_POSITION]; // cappi - - if (PlasticDissipation < 1.0) { - const double ro = std::sqrt(1.0 - initial_threshold / ultimate_stress); - double alpha = std::log((1.0 - (1.0 - ro) * (1.0 - ro)) / ((3.0 - ro) * (1.0 + ro) * max_stress_position)); - alpha = std::exp(alpha / (1.0 - max_stress_position)); - const double phi = std::pow((1.0 - ro), 2.0) + ((3.0 - ro) * (1.0 + ro) * PlasticDissipation * (std::pow(alpha, (1.0 - PlasticDissipation)))); - - rEquivalentStressThreshold = ultimate_stress * (2.0 * std::sqrt(phi) - phi); - rSlope = ultimate_stress * ((1.0 / std::sqrt(phi)) - 1.0) * (3.0 - ro) * (1.0 + ro) * (std::pow(alpha, (1.0 - PlasticDissipation))) * - (1.0 - std::log(alpha) * PlasticDissipation); - } else { - KRATOS_ERROR << "PlasticDissipation > 1.0 " << PlasticDissipation << std::endl; - } + GenericConstitutiveLawIntegratorPlasticity::CalculateEquivalentStressThresholdHardeningCurveInitialHardeningExponentialSoftening( + PlasticDissipation,TensileIndicatorFactor,CompressionIndicatorFactor,rEquivalentStressThreshold,rSlope,rValues); } /** @@ -672,11 +525,8 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity ConstitutiveLaw::Parameters& rValues ) { - double initial_threshold; - GetInitialUniaxialThreshold(rValues, initial_threshold); - - rEquivalentStressThreshold = initial_threshold; - rSlope = -0.5 * initial_threshold; + GenericConstitutiveLawIntegratorPlasticity::CalculateEquivalentStressThresholdHardeningCurvePerfectPlasticity( + PlasticDissipation,TensileIndicatorFactor,CompressionIndicatorFactor,rEquivalentStressThreshold,rSlope,rValues); } /** @@ -701,84 +551,9 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity const double CharacteristicLength ) { - const Properties& r_material_properties = rValues.GetMaterialProperties(); - const Vector& curve_fitting_parameters = r_material_properties[CURVE_FITTING_PARAMETERS]; - - const bool has_tangency_linear_region = r_material_properties.Has(TANGENCY_REGION2); - const bool tangency_linear_region = has_tangency_linear_region ? r_material_properties[TANGENCY_REGION2] : false; - - const Vector& plastic_strain_indicators = r_material_properties[PLASTIC_STRAIN_INDICATORS]; - const double fracture_energy = r_material_properties[FRACTURE_ENERGY]; - const double volumetric_fracture_energy = fracture_energy / CharacteristicLength; - - const SizeType order_polinomial = curve_fitting_parameters.size(); - const double plastic_strain_indicator_1 = plastic_strain_indicators[0]; - const double plastic_strain_indicator_2 = plastic_strain_indicators[1]; - - // Compute the initial and the final stresses - double stress_indicator_1 = curve_fitting_parameters[0]; - double dS_dEp = 0.0; - - for (IndexType i = 1; i < order_polinomial; ++i) { - stress_indicator_1 += curve_fitting_parameters[i] * (std::pow(plastic_strain_indicator_1, i)); - dS_dEp += i * curve_fitting_parameters[i] * std::pow(plastic_strain_indicator_1, i - 1); - } - - double dKp_dEp = stress_indicator_1 / volumetric_fracture_energy; - if (!tangency_linear_region){ - dS_dEp = 0.0; // initial slope is zero, else the slope is the tangent of the polinomial region. - } - - const double stress_indicator_2 = stress_indicator_1 + dS_dEp * (plastic_strain_indicator_2 - plastic_strain_indicator_1); - - // Compute volumetric fracture energies of each region - double Gt1 = 0.0; - for (IndexType i = 0; i < order_polinomial; ++i) { - Gt1 += curve_fitting_parameters[i] * (std::pow(plastic_strain_indicator_1, i + 1)) / (i + 1); - } - const double Gt2 = (stress_indicator_1 + stress_indicator_2) * (plastic_strain_indicator_2 - plastic_strain_indicator_1) * 0.5; - const double Gt3 = volumetric_fracture_energy - Gt2 - Gt1; - - KRATOS_ERROR_IF(Gt3 < 0.0) << "Fracture energy too low in CurveFittingHardening of plasticity..." << std::endl; - - // Compute segment threshold - const double segment_threshold = (Gt2 + Gt1) / volumetric_fracture_energy; - - if (PlasticDissipation <= segment_threshold) { - const double Eps = EquivalentPlasticStrain; - - if (EquivalentPlasticStrain < plastic_strain_indicator_1) { // Polinomial region - double S_Ep = curve_fitting_parameters[0]; - double dS_dEp = 0.0; - for (IndexType i = 1; i < order_polinomial; ++i) { - S_Ep += curve_fitting_parameters[i] * std::pow(Eps, i); - dS_dEp += i * curve_fitting_parameters[i] * std::pow(Eps, i - 1); - } - dKp_dEp = S_Ep / volumetric_fracture_energy; - - rEquivalentStressThreshold = S_Ep; - rSlope = dS_dEp / dKp_dEp; - } else { // Linear region - const double S_Ep = stress_indicator_1 + (stress_indicator_2 - stress_indicator_1) / (plastic_strain_indicator_2 - plastic_strain_indicator_1) * (Eps - plastic_strain_indicator_1); - double dS_dEp = (stress_indicator_2 - stress_indicator_1) / (plastic_strain_indicator_2 - plastic_strain_indicator_1); - dKp_dEp = S_Ep / volumetric_fracture_energy; - - rEquivalentStressThreshold = S_Ep; - rSlope = dS_dEp / dKp_dEp; - } - } else { // Exponential softening - const double Eps = EquivalentPlasticStrain; - const double alpha = std::pow(stress_indicator_1, 2); - const double beta = (std::pow(stress_indicator_2, 2) - alpha) / (plastic_strain_indicator_2 - plastic_strain_indicator_1); - - const double S_Ep = std::sqrt(alpha + beta * (Eps - plastic_strain_indicator_1)); - const double plastic_dissipation_region_3 = PlasticDissipation - segment_threshold; - - const double beta2 = 1.5 * S_Ep / Gt3; - const double alpha2 = std::sqrt((plastic_dissipation_region_3 * 2.0 * beta2 * volumetric_fracture_energy / S_Ep) + 1.0); - rEquivalentStressThreshold = S_Ep * alpha2 * (2.0 - alpha2); - rSlope = 2.0 * beta2 * volumetric_fracture_energy * (1.0 / alpha2 - 1.0); - } + GenericConstitutiveLawIntegratorPlasticity::CalculateEquivalentStressThresholdCurveFittingHardening( + PlasticDissipation,TensileIndicatorFactor,CompressionIndicatorFactor,rEquivalentStressThreshold,rSlope,rValues, + EquivalentPlasticStrain,CharacteristicLength); } /** @@ -799,14 +574,8 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity double& rEquivalentPlasticStrain ) { - double scalar_product = 0.0; - for (IndexType i = 0; i < rPlasticStrain.size(); ++i) { - scalar_product += rStressVector[i] * rPlasticStrain[i]; - } - - /*Since this law is used for Von Mises and Tresca, no - scaling is necessary, even though the needed params are available*/ - rEquivalentPlasticStrain = scalar_product / UniaxialStress; + GenericConstitutiveLawIntegratorPlasticity::CalculateEquivalentPlasticStrain( + rStressVector,UniaxialStress,rPlasticStrain,r0,rValues,rEquivalentPlasticStrain); } /** @@ -833,14 +602,8 @@ class GenericConstitutiveLawIntegratorKinematicPlasticity double& rHardeningParameter ) { - rHardeningParameter = SlopeThreshold; - double aux = 0.0; - - for (IndexType i = 0; i < VoigtSize; ++i) { - aux += rHCapa[i] * rGFlux[i]; - } - if (aux != 0.0) - rHardeningParameter *= aux; + GenericConstitutiveLawIntegratorPlasticity::CalculateHardeningParameter( + rGFlux,SlopeThreshold,rHCapa,rHardeningParameter); } /** diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_plasticity.h b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_plasticity.h index f3b54357bcc0..eae8ee83ba2d 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_plasticity.h +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_plasticity.h @@ -100,7 +100,8 @@ class GenericConstitutiveLawIntegratorPlasticity ExponentialSoftening = 1, InitialHardeningExponentialSoftening = 2, PerfectPlasticity = 3, - CurveFittingHardening = 4 + CurveFittingHardening = 4, + LinearExponentialSoftening = 5 }; ///@} @@ -197,10 +198,8 @@ class GenericConstitutiveLawIntegratorPlasticity iteration++; } } + KRATOS_WARNING_IF("GenericConstitutiveLawIntegratorPlasticity", iteration > max_iter) << "Maximum number of iterations in plasticity loop reached..." << std::endl; - if (iteration > max_iter) { - KRATOS_WARNING_FIRST_N("Backward Euler Plasticity", 20) << "Maximum number of iterations in plasticity loop reached..." << std::endl; - } } /** @@ -371,12 +370,12 @@ class GenericConstitutiveLawIntegratorPlasticity const double yield_tension = has_symmetric_yield_stress ? r_material_properties[YIELD_STRESS] : r_material_properties[YIELD_STRESS_TENSION]; const double n = yield_compression / yield_tension; const double fracture_energy_tension = r_material_properties[FRACTURE_ENERGY]; // Frac energy in tension - const double fracture_energy_comprression = r_material_properties[FRACTURE_ENERGY] * std::pow(n, 2); // Frac energy in compression + const double fracture_energy_compression = r_material_properties[FRACTURE_ENERGY] * std::pow(n, 2); // Frac energy in compression const double characteristic_fracture_energy_tension = fracture_energy_tension / CharacteristicLength; - const double characteristic_fracture_energy_compression = fracture_energy_comprression / CharacteristicLength; + const double characteristic_fracture_energy_compression = fracture_energy_compression / CharacteristicLength; - const double hlim = 2.0 * young_modulus * characteristic_fracture_energy_compression / (std::pow(yield_compression, 2)); + const double hlim = 2.0 * young_modulus * fracture_energy_compression / (std::pow(yield_compression, 2)); KRATOS_ERROR_IF(CharacteristicLength > hlim) << "The Fracture Energy is to low: " << characteristic_fracture_energy_compression << std::endl; double constant0 = 0.0, constant1 = 0.0, dplastic_dissipation = 0.0; @@ -444,7 +443,7 @@ class GenericConstitutiveLawIntegratorPlasticity CalculateEquivalentStressThresholdHardeningCurveExponentialSoftening( PlasticDissipation, TensileIndicatorFactor, CompressionIndicatorFactor, eq_thresholds[i], slopes[i], - rValues); + rValues, CharacteristicLength); break; case HardeningCurveType::InitialHardeningExponentialSoftening: @@ -468,6 +467,13 @@ class GenericConstitutiveLawIntegratorPlasticity rValues, EquivalentPlasticStrain, CharacteristicLength); break; + case HardeningCurveType::LinearExponentialSoftening: + CalculateEquivalentStressThresholdHardeningCurveLinearExponentialSoftening( + PlasticDissipation, TensileIndicatorFactor, + CompressionIndicatorFactor, eq_thresholds[i], slopes[i], CharacteristicLength, + rValues); + break; + // Add more cases... default: @@ -498,11 +504,19 @@ class GenericConstitutiveLawIntegratorPlasticity ConstitutiveLaw::Parameters& rValues ) { + const Properties& r_material_properties = rValues.GetMaterialProperties(); + const bool has_plastic_dissipation_limit = r_material_properties.Has(PLASTIC_DISSIPATION_LIMIT_LINEAR_SOFTENING); + const double plastic_dissipation_limit = has_plastic_dissipation_limit ? r_material_properties[PLASTIC_DISSIPATION_LIMIT_LINEAR_SOFTENING] : 0.99; double initial_threshold; GetInitialUniaxialThreshold(rValues, initial_threshold); - rEquivalentStressThreshold = initial_threshold * std::sqrt(1.0 - PlasticDissipation); - rSlope = -0.5 * (std::pow(initial_threshold, 2.0) / (rEquivalentStressThreshold)); + if (PlasticDissipation <= plastic_dissipation_limit){ //Linear branch + rEquivalentStressThreshold = initial_threshold * std::sqrt(1.0 - PlasticDissipation); + rSlope = -0.5 * (std::pow(initial_threshold, 2.0) / (rEquivalentStressThreshold)); + } else { //Exponential branch included to achieve consistent results after full plasticity scenarios + rEquivalentStressThreshold = (initial_threshold / std::sqrt(1.0 - plastic_dissipation_limit)) * (1.0 - PlasticDissipation); + rSlope = - (initial_threshold / std::sqrt(1.0 - plastic_dissipation_limit)); + } } /** @@ -513,6 +527,7 @@ class GenericConstitutiveLawIntegratorPlasticity * @param rEquivalentStressThreshold The maximum uniaxial stress of the linear behaviour * @param rSlope The slope of the PlasticDiss-Threshold curve * @param rValues Parameters of the constitutive law + * @param CharacteristicLength Characteristic length of the finite element */ static void CalculateEquivalentStressThresholdHardeningCurveExponentialSoftening( const double PlasticDissipation, @@ -520,14 +535,36 @@ class GenericConstitutiveLawIntegratorPlasticity const double CompressionIndicatorFactor, double& rEquivalentStressThreshold, double& rSlope, - ConstitutiveLaw::Parameters& rValues + ConstitutiveLaw::Parameters& rValues, + const double CharacteristicLength ) { + const Properties& r_material_properties = rValues.GetMaterialProperties(); + + const double young_modulus = r_material_properties[YOUNG_MODULUS]; + const bool has_symmetric_yield_stress = r_material_properties.Has(YIELD_STRESS); + const double yield_compression = has_symmetric_yield_stress ? r_material_properties[YIELD_STRESS] : r_material_properties[YIELD_STRESS_COMPRESSION]; + const double yield_tension = has_symmetric_yield_stress ? r_material_properties[YIELD_STRESS] : r_material_properties[YIELD_STRESS_TENSION]; + const double n = yield_compression / yield_tension; + const double fracture_energy_compression = r_material_properties[FRACTURE_ENERGY] * std::pow(n, 2); // Frac energy in compression + const double characteristic_fracture_energy_compression = fracture_energy_compression / CharacteristicLength; + + const double minimum_characteristic_fracture_energy_exponential_softening = (std::pow(yield_compression, 2)) / young_modulus; + double initial_threshold; GetInitialUniaxialThreshold(rValues, initial_threshold); - rEquivalentStressThreshold = initial_threshold * (1.0 - PlasticDissipation); - rSlope = - initial_threshold; + if ( characteristic_fracture_energy_compression >= minimum_characteristic_fracture_energy_exponential_softening){ // Exponential softening + // KRATOS_WATCH("ahora") + rEquivalentStressThreshold = initial_threshold * (1.0 - PlasticDissipation); + rSlope = - initial_threshold; + } else { //Linear softening which is the one that requires minimum fracture energy + KRATOS_WATCH("here") + CalculateEquivalentStressThresholdHardeningCurveLinearSoftening( + PlasticDissipation, TensileIndicatorFactor, + CompressionIndicatorFactor, rEquivalentStressThreshold, rSlope, + rValues); + } } /** @@ -591,7 +628,7 @@ class GenericConstitutiveLawIntegratorPlasticity GetInitialUniaxialThreshold(rValues, initial_threshold); rEquivalentStressThreshold = initial_threshold; - rSlope = -0.5 * initial_threshold; + rSlope = 0.0; } /** @@ -697,6 +734,48 @@ class GenericConstitutiveLawIntegratorPlasticity } + /** + * @brief This method computes the uniaxial threshold using a linear-exponential softening, which changes from one to the other through the platic_dissipation_limit + * @param PlasticDissipation The internal variable of energy dissipation due to plasticity + * @param TensileIndicatorFactor The tensile indicator + * @param CompressionIndicatorFactor The compressive indicator + * @param rEquivalentStressThreshold The maximum uniaxial stress of the linear behaviour + * @param rSlope The slope of the PlasticDiss-Threshold curve + * @param CharacteristicLength Characteristic length of the finite element + * @param rValues Parameters of the constitutive law + */ + static void CalculateEquivalentStressThresholdHardeningCurveLinearExponentialSoftening( + const double PlasticDissipation, + const double TensileIndicatorFactor, + const double CompressionIndicatorFactor, + double& rEquivalentStressThreshold, + double& rSlope, + const double CharacteristicLength, + ConstitutiveLaw::Parameters& rValues + ) + { + const Properties& r_material_properties = rValues.GetMaterialProperties(); + const bool has_plastic_dissipation_limit = r_material_properties.Has(PLASTIC_DISSIPATION_LIMIT_LINEAR_SOFTENING); + + const double plastic_dissipation_limit = has_plastic_dissipation_limit ? r_material_properties[PLASTIC_DISSIPATION_LIMIT_LINEAR_SOFTENING] : 0.9; + const double fracture_energy = r_material_properties[FRACTURE_ENERGY]; + const double volumetric_fracture_energy = fracture_energy / CharacteristicLength; + double initial_threshold; + GetInitialUniaxialThreshold(rValues, initial_threshold); + + const double volumetric_fracture_energy_linear_branch = 0.5 * volumetric_fracture_energy * (plastic_dissipation_limit + 1.0); + + if (PlasticDissipation <= plastic_dissipation_limit){ //Linear branch + rEquivalentStressThreshold = initial_threshold * std::sqrt(1.0 - PlasticDissipation * volumetric_fracture_energy / volumetric_fracture_energy_linear_branch); + rSlope = - 0.5 * initial_threshold * (volumetric_fracture_energy / volumetric_fracture_energy_linear_branch) * std::pow(1.0 - PlasticDissipation * volumetric_fracture_energy / volumetric_fracture_energy_linear_branch, -0.5); + } else { //Exponential branch included to achieve consistent results after full plasticity scenarios + const double volumetric_fracture_energy_exponential_branch = volumetric_fracture_energy * (1.0 - plastic_dissipation_limit) * std::exp((plastic_dissipation_limit + 1.0) / (std::sqrt(1.0 - std::pow(plastic_dissipation_limit, 2.0))) - 1.0); + const double initial_threshold_exponential = initial_threshold * volumetric_fracture_energy_exponential_branch / volumetric_fracture_energy * std::sqrt(1.0 - plastic_dissipation_limit * volumetric_fracture_energy / volumetric_fracture_energy_linear_branch) / (1.0 - plastic_dissipation_limit); + rEquivalentStressThreshold = initial_threshold_exponential * (1.0 - PlasticDissipation) * volumetric_fracture_energy / volumetric_fracture_energy_exponential_branch; + rSlope = - initial_threshold_exponential * volumetric_fracture_energy / volumetric_fracture_energy_exponential_branch; + } + } + /** * @brief This method returns the equivalent plastic strain * @param rThreshold The uniaxial stress threshold diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_finite_strain_constitutive_law_integrator_kinematic_plasticity.h b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_finite_strain_constitutive_law_integrator_kinematic_plasticity.h index fb332f4195f2..892e306b9324 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_finite_strain_constitutive_law_integrator_kinematic_plasticity.h +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_finite_strain_constitutive_law_integrator_kinematic_plasticity.h @@ -244,17 +244,11 @@ class GenericFiniteStrainConstitutiveLawIntegratorKinematicPlasticity while (iteration <= max_iter) { // With this we can compute the polar decomposition in order to compute the Ren+1 ConstitutiveLawUtilities::PolarDecomposition(elastic_deformation_matrix, Re, Ue); - noalias(elastic_deformation_matrix) = ConstitutiveLawUtilities::CalculateDirectElasticDeformationGradient(trial_elastic_deformation_matrix, rPlasticPotentialDerivative, plastic_consistency_factor_increment, Re); - // We calculate the plastic consistency factor plastic_consistency_factor_increment = threshold_indicator * rPlasticDenominator; if (plastic_consistency_factor_increment < 0.0) plastic_consistency_factor_increment = 0.0; // NOTE: It could be useful, maybe - -// noalias(plastic_deformation_gradient_increment) = ConstitutiveLawUtilities::CalculateLinearPlasticDeformationGradientIncrement(rPlasticPotentialDerivative, plastic_consistency_factor_increment); noalias(plastic_deformation_gradient_increment) = ConstitutiveLawUtilities::CalculateDirectPlasticDeformationGradientIncrement(rPlasticPotentialDerivative, plastic_consistency_factor_increment, Re); -// noalias(plastic_deformation_gradient_increment) = ConstitutiveLawUtilities::CalculateExponentialPlasticDeformationGradientIncrement(rPlasticPotentialDerivative, plastic_consistency_factor_increment, Re); - // We check that the increment is not a zero matrix or to big const double norm_increment = norm_frobenius(plastic_deformation_gradient_increment); if (norm_increment < 1.0e-8 @@ -266,18 +260,15 @@ class GenericFiniteStrainConstitutiveLawIntegratorKinematicPlasticity noalias(rPredictiveStressVector) = aux_vector; break; } - // The increment of the deformation is not added but multiplied in finite strain noalias(rPlasticDeformationGradient) = prod(plastic_deformation_gradient_increment, previous_plastic_deformation_gradient); rValues.SetDeterminantF(MathUtils::Det(plastic_deformation_gradient_increment)); rValues.SetDeformationGradientF(plastic_deformation_gradient_increment); rConstitutiveLaw.CalculateValue(rValues, rStrainVariable, delta_plastic_strain); - // We compute the plastic strain rValues.SetDeterminantF(MathUtils::Det(rPlasticDeformationGradient)); rValues.SetDeformationGradientF(rPlasticDeformationGradient); rConstitutiveLaw.CalculateValue(rValues, rStrainVariable, plastic_strain); - // We compute the new predictive stress vector MathUtils::InvertMatrix(plastic_deformation_gradient_increment, inverse_plastic_deformation_gradient, aux_det); predictive_deformation_gradient = prod(inverse_plastic_deformation_gradient, predictive_deformation_gradient); @@ -285,26 +276,21 @@ class GenericFiniteStrainConstitutiveLawIntegratorKinematicPlasticity rValues.SetDeformationGradientF(predictive_deformation_gradient); rConstitutiveLaw.CalculateValue(rValues, rStressVariable, aux_vector); noalias(rPredictiveStressVector) = aux_vector; - // Calculate back-stress SmallStrainIntegratorType::CalculateBackStress(rPredictiveStressVector, rValues, previous_stress_vector, - delta_plastic_strain, rBackStressVector); - + delta_plastic_strain, rBackStressVector); // Calculate plastic parameters noalias(kin_hard_stress_vector) = rPredictiveStressVector - rBackStressVector; threshold_indicator = CalculatePlasticParameters(kin_hard_stress_vector, rStrainVector, rUniaxialStress, rThreshold, - rPlasticDenominator, rYieldSurfaceDerivative, rPlasticPotentialDerivative, - rPlasticDissipation, delta_plastic_strain, rConstitutiveMatrix, rValues, CharacteristicLength, plastic_strain, rBackStressVector); - + rPlasticDenominator, rYieldSurfaceDerivative, rPlasticPotentialDerivative, + rPlasticDissipation, delta_plastic_strain, rConstitutiveMatrix, rValues, CharacteristicLength, plastic_strain, rBackStressVector); if (threshold_indicator <= std::abs(1.0e-4 * rThreshold)) { // Has converged break; } else { ++iteration; } } - rValues = values_backup; - if (iteration > max_iter) { KRATOS_WARNING_FIRST_N("Backward Euler Plasticity", 20) << "Maximum number of iterations in plasticity loop reached..." << std::endl; } diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_finite_strain_constitutive_law_integrator_plasticity.h b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_finite_strain_constitutive_law_integrator_plasticity.h index 513ccefae603..61f8bf4d96d5 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_finite_strain_constitutive_law_integrator_plasticity.h +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/generic_finite_strain_constitutive_law_integrator_plasticity.h @@ -232,17 +232,11 @@ class GenericFiniteStrainConstitutiveLawIntegratorPlasticity while (iteration <= max_iter) { // With this we can compute the polar decomposition in order to compute the Ren+1 ConstitutiveLawUtilities::PolarDecomposition(elastic_deformation_matrix, Re, Ue); - noalias(elastic_deformation_matrix) = ConstitutiveLawUtilities::CalculateDirectElasticDeformationGradient(trial_elastic_deformation_matrix, rPlasticPotentialDerivative, plastic_consistency_factor_increment, Re); - // We calculate the plastic consistency factor plastic_consistency_factor_increment = threshold_indicator * rPlasticDenominator; if (plastic_consistency_factor_increment < 0.0) plastic_consistency_factor_increment = 0.0; // NOTE: It could be useful, maybe - -// noalias(plastic_deformation_gradient_increment) = ConstitutiveLawUtilities::CalculateLinearPlasticDeformationGradientIncrement(rPlasticPotentialDerivative, plastic_consistency_factor_increment); noalias(plastic_deformation_gradient_increment) = ConstitutiveLawUtilities::CalculateDirectPlasticDeformationGradientIncrement(rPlasticPotentialDerivative, plastic_consistency_factor_increment, Re); -// noalias(plastic_deformation_gradient_increment) = ConstitutiveLawUtilities::CalculateExponentialPlasticDeformationGradientIncrement(rPlasticPotentialDerivative, plastic_consistency_factor_increment, Re); - // We check that the increment is not a zero matrix or to big const double norm_increment = norm_frobenius(plastic_deformation_gradient_increment); if (norm_increment < 1.0e-8 @@ -254,18 +248,15 @@ class GenericFiniteStrainConstitutiveLawIntegratorPlasticity noalias(rPredictiveStressVector) = aux_vector; break; } - // The increment of the deformation is not added but multiplied in finite strain noalias(rPlasticDeformationGradient) = prod(plastic_deformation_gradient_increment, previous_plastic_deformation_gradient); rValues.SetDeterminantF(MathUtils::Det(plastic_deformation_gradient_increment)); rValues.SetDeformationGradientF(plastic_deformation_gradient_increment); rConstitutiveLaw.CalculateValue(rValues, rStrainVariable, delta_plastic_strain); - // We compute the plastic strain rValues.SetDeterminantF(MathUtils::Det(rPlasticDeformationGradient)); rValues.SetDeformationGradientF(rPlasticDeformationGradient); rConstitutiveLaw.CalculateValue(rValues, rStrainVariable, plastic_strain); - // We compute the new predictive stress vector MathUtils::InvertMatrix(plastic_deformation_gradient_increment, inverse_plastic_deformation_gradient, aux_det); predictive_deformation_gradient = prod(inverse_plastic_deformation_gradient, predictive_deformation_gradient); @@ -273,21 +264,17 @@ class GenericFiniteStrainConstitutiveLawIntegratorPlasticity rValues.SetDeformationGradientF(predictive_deformation_gradient); rConstitutiveLaw.CalculateValue(rValues, rStressVariable, aux_vector); noalias(rPredictiveStressVector) = aux_vector; - // Calculate plastic parameters threshold_indicator = CalculatePlasticParameters(rPredictiveStressVector, rStrainVector, rUniaxialStress, rThreshold, - rPlasticDenominator, rYieldSurfaceDerivative, rPlasticPotentialDerivative, - rPlasticDissipation, delta_plastic_strain, rConstitutiveMatrix, rValues, CharacteristicLength, plastic_strain); - + rPlasticDenominator, rYieldSurfaceDerivative, rPlasticPotentialDerivative, + rPlasticDissipation, delta_plastic_strain, rConstitutiveMatrix, rValues, CharacteristicLength, plastic_strain); if (threshold_indicator <= std::abs(1.0e-4 * rThreshold)) { // Has converged break; } else { ++iteration; } } - rValues = values_backup; - if (iteration > max_iter) { KRATOS_WARNING_FIRST_N("Backward Euler Plasticity", 20) << "Maximum number of iterations in plasticity loop reached..." << std::endl; } diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/high_cycle_fatigue_law_integrator.h b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/high_cycle_fatigue_law_integrator.h index 3a9180f8aef2..2c7083613383 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/high_cycle_fatigue_law_integrator.h +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/constitutive_laws_integrators/high_cycle_fatigue_law_integrator.h @@ -27,7 +27,7 @@ namespace Kratos // The size type definition typedef std::size_t SizeType; - + ///@} ///@name Enum's ///@{ @@ -91,16 +91,16 @@ class HighCycleFatigueLawIntegrator /** * @brief This method checks and saves the previous stress state if it was a maximum or a minimum. * @param CurrentStress Equivalent stress in the current step. - * @param rMaximumStress Maximum stress. - * @param rMinimumStress Minimum stress. - * @param PreviousStresses Equivalent stresses in the two previous steps. - * @param rMaxIndicator Indicator of a maximum in the current cycle. - * @param rMinIndicator Indicator of a minimum in the current cycle. + * @param rMaximumStress Maximum stress. + * @param rMinimumStress Minimum stress. + * @param PreviousStresses Equivalent stresses in the two previous steps. + * @param rMaxIndicator Indicator of a maximum in the current cycle. + * @param rMinIndicator Indicator of a minimum in the current cycle. */ static void CalculateMaximumAndMinimumStresses( const double CurrentStress, - double& rMaximumStress, - double& rMinimumStress, + double& rMaximumStress, + double& rMinimumStress, const Vector PreviousStresses, bool& rMaxIndicator, bool& rMinIndicator) @@ -109,21 +109,20 @@ class HighCycleFatigueLawIntegrator const double stress_2 = PreviousStresses[0]; const double stress_increment_1 = stress_1 - stress_2; const double stress_increment_2 = CurrentStress - stress_1; - - if (stress_increment_1 >= 1.0e-3 && stress_increment_2 <= 0.0) { + if (stress_increment_1 > 1.0e-3 && stress_increment_2 < -1.0e-3) { rMaximumStress = stress_1; rMaxIndicator = true; - } else if (stress_increment_1 <= -1.0e-3 && stress_increment_2 >= 0.0) { + } else if (stress_increment_1 < -1.0e-3 && stress_increment_2 > 1.0e-3) { rMinimumStress = stress_1; rMinIndicator = true; } } /** - * @brief This method checks if the global stress state is tension or compression; -1 for a generalized compression state and 1 for a generalized tensile state. + * @brief This method checks if the global stress state is tension or compression; -1 for a generalized compression state and 1 for a generalized tensile state. * @param StressVector Current predictive stress tensor. */ - static double CalculateTensionCompressionFactor(const Vector& rStressVector) + static double CalculateTensionCompressionFactor(const Vector& rStressVector) { array_1d principal_stresses; ConstitutiveLawUtilities<6>::CalculatePrincipalStresses(principal_stresses, rStressVector); @@ -145,9 +144,9 @@ class HighCycleFatigueLawIntegrator } /** - * @brief This method returns de reversion factor + * @brief This method returns de reversion factor * @param MaxStress Signed maximum equivalent stress in the current cycle. - * @param MinStress Signed minimum equivalent stress in the current cycle. + * @param MinStress Signed minimum equivalent stress in the current cycle. */ static double CalculateReversionFactor(const double MaxStress, const double MinStress) { @@ -155,12 +154,12 @@ class HighCycleFatigueLawIntegrator } /** - * @brief This method computes internal variables (B0, Sth and ALPHAT) of the CL + * @brief This method computes internal variables (B0, Sth and ALPHAT) of the CL * @param MaxStress Signed maximum stress in the current cycle. * @param ReversionFactor Ratio between the minimum and maximum signed equivalent stresses for the current load cycle. * @param MaterialParameters Material properties. * @param rB0 Internal variable of the fatigue model. - * @param rSth Internal variable of the fatigue model of the fatigue model. + * @param rSth Endurance limit of the fatigue model. * @param rAlphat Internal variable of the fatigue model. */ static void CalculateFatigueParameters(const double MaxStress, @@ -168,14 +167,15 @@ class HighCycleFatigueLawIntegrator const Properties& rMaterialParameters, double& rB0, double& rSth, - double& rAlphat) + double& rAlphat, + double& rN_f) { const Vector& r_fatigue_coefficients = rMaterialParameters[HIGH_CYCLE_FATIGUE_COEFFICIENTS]; const double yield_stress = rMaterialParameters.Has(YIELD_STRESS) ? rMaterialParameters[YIELD_STRESS] : rMaterialParameters[YIELD_STRESS_TENSION]; //These variables have been defined following the model described by S. Oller et al. in A continuum mechanics model for mechanical fatigue analysis (2005), equation 13 on page 184. const double Se = r_fatigue_coefficients[0] * yield_stress; - const double STHR1 = r_fatigue_coefficients[1]; + const double STHR1 = r_fatigue_coefficients[1]; const double STHR2 = r_fatigue_coefficients[2]; const double ALFAF = r_fatigue_coefficients[3]; const double BETAF = r_fatigue_coefficients[4]; @@ -192,13 +192,13 @@ class HighCycleFatigueLawIntegrator const double square_betaf = std::pow(BETAF, 2.0); if (MaxStress > rSth && MaxStress <= yield_stress) { - const double N_F = std::pow(10.0,std::pow(-std::log((MaxStress - rSth) / (yield_stress - rSth))/rAlphat,(1.0/BETAF))); - rB0 = -(std::log(MaxStress / yield_stress) / std::pow((std::log10(N_F)), square_betaf)); + rN_f = std::pow(10.0,std::pow(-std::log((MaxStress - rSth) / (yield_stress - rSth))/rAlphat,(1.0/BETAF))); + rB0 = -(std::log(MaxStress / yield_stress) / std::pow((std::log10(rN_f)), square_betaf)); } } /** - * @brief This method computes the reduction factor and the wohler stress (SN curve) + * @brief This method computes the reduction factor and the wohler stress (SN curve) * @param MaterialParameters Material properties. * @param MaxStress Signed maximum stress in the current cycle. * @param LocalNumberOfCycles Number of cycles in the current load. @@ -224,9 +224,9 @@ class HighCycleFatigueLawIntegrator const double yield_stress = rMaterialParameters.Has(YIELD_STRESS) ? rMaterialParameters[YIELD_STRESS] : rMaterialParameters[YIELD_STRESS_TENSION]; rWohlerStress = (Sth + (yield_stress - Sth) * std::exp(-Alphat * (std::pow(std::log10(static_cast(LocalNumberOfCycles)), BETAF)))) / yield_stress; } - if (MaxStress > Sth) { rFatigueReductionFactor = std::exp(-B0 * std::pow(std::log10(static_cast(LocalNumberOfCycles)), (BETAF * BETAF))); + rFatigueReductionFactor = (rFatigueReductionFactor < 0.01) ? 0.01 : rFatigueReductionFactor; } } diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_high_cycle_fatigue_law.cpp b/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_high_cycle_fatigue_law.cpp index fb48113f7344..fcf65c1502cd 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_high_cycle_fatigue_law.cpp +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_high_cycle_fatigue_law.cpp @@ -17,6 +17,7 @@ // Project includes #include "custom_utilities/tangent_operator_calculator_utility.h" #include "structural_mechanics_application_variables.h" +#include "constitutive_laws_application_variables.h" #include "custom_constitutive/generic_small_strain_high_cycle_fatigue_law.h" #include "custom_constitutive/constitutive_laws_integrators/generic_constitutive_law_integrator_damage.h" #include "custom_constitutive/constitutive_laws_integrators/high_cycle_fatigue_law_integrator.h" @@ -53,7 +54,7 @@ void GenericSmallStrainHighCycleFatigueLaw::CalculateMa //NOTE: SINCE THE ELEMENT IS IN SMALL STRAINS WE CAN USE ANY STRAIN MEASURE. HERE EMPLOYING THE CAUCHY_GREEN if (r_constitutive_law_options.IsNot( ConstitutiveLaw::USE_ELEMENT_PROVIDED_STRAIN)) { - GenericSmallStrainIsotropicDamage::CalculateValue(rValues, STRAIN, r_strain_vector); + BaseType::CalculateValue(rValues, STRAIN, r_strain_vector); } // Elastic Matrix @@ -77,59 +78,59 @@ void GenericSmallStrainHighCycleFatigueLaw::CalculateMa double uniaxial_stress; TConstLawIntegratorType::YieldSurfaceType::CalculateEquivalentStress(predictive_stress_vector, r_strain_vector, uniaxial_stress, rValues); - double max_stress = this->GetMaxStress(); - double min_stress = this->GetMinStress(); - double sign_factor = HighCycleFatigueLawIntegrator<6>::CalculateTensionCompressionFactor(predictive_stress_vector); - uniaxial_stress *= sign_factor; - unsigned int global_number_of_cycles = this->GetNumberOfCyclesGlobal(); - unsigned int local_number_of_cycles = this->GetNumberOfCyclesLocal(); - bool max_indicator = this->GetMaxDetected(); - bool min_indicator = this->GetMinDetected(); - double fatigue_reduction_factor = this->GetFatigueReductionFactor(); - double B0 = this->GetFatigueReductionParameter(); - double previous_max_stress = this->GetPreviousMaxStress(); - double previous_min_stress = this->GetPreviousMinStress(); - double wohler_stress = this->GetWohlerStress(); - + const double max_stress = mMaxStress; + const double min_stress = mMinStress; + unsigned int global_number_of_cycles = mNumberOfCyclesGlobal; + unsigned int local_number_of_cycles = mNumberOfCyclesLocal; + bool max_indicator = mMaxDetected; + bool min_indicator = mMinDetected; + double fatigue_reduction_factor = mFatigueReductionFactor; + double B0 = mFatigueReductionParameter; + double previous_max_stress = mPreviousMaxStress; + double previous_min_stress = mPreviousMinStress; + double wohler_stress = mWohlerStress; + double reversion_factor_relative_error = mReversionFactorRelativeError; + double max_stress_relative_error = mMaxStressRelativeError; + double CyclesToFailure = mCyclesToFailure; + bool new_cycle = false; + double s_th = mThresholdStress; + bool adnvance_strategy_applied = rValues.GetProcessInfo()[ADVANCE_STRATEGY_APPLIED]; + bool damage_activation = rValues.GetProcessInfo()[DAMAGE_ACTIVATION]; if (r_constitutive_law_options.Is(ConstitutiveLaw::COMPUTE_CONSTITUTIVE_TENSOR)) { - HighCycleFatigueLawIntegrator<6>::CalculateMaximumAndMinimumStresses( - uniaxial_stress, - max_stress, - min_stress, - this->GetPreviousStresses(), - max_indicator, - min_indicator); - this->SetMaxStress(max_stress); - this->SetMinStress(min_stress); - if (max_indicator && min_indicator) { - double previous_reversion_factor = HighCycleFatigueLawIntegrator<6>::CalculateReversionFactor(previous_max_stress, previous_min_stress); - double reversion_factor = HighCycleFatigueLawIntegrator<6>::CalculateReversionFactor(max_stress, min_stress); - - double s_th, alphat; + const double previous_reversion_factor = HighCycleFatigueLawIntegrator<6>::CalculateReversionFactor(previous_max_stress, previous_min_stress); + const double reversion_factor = HighCycleFatigueLawIntegrator<6>::CalculateReversionFactor(max_stress, min_stress); + double alphat; HighCycleFatigueLawIntegrator<6>::CalculateFatigueParameters( max_stress, reversion_factor, rValues.GetMaterialProperties(), B0, s_th, - alphat); + alphat, + CyclesToFailure); double betaf = rValues.GetMaterialProperties()[HIGH_CYCLE_FATIGUE_COEFFICIENTS][4]; - double reversion_factor_relative_error = std::abs((previous_reversion_factor - reversion_factor) / previous_reversion_factor); - double max_stress_relative_error = std::abs((previous_reversion_factor - reversion_factor) / previous_reversion_factor); + if (std::abs(min_stress) < 0.001) { + reversion_factor_relative_error = std::abs(reversion_factor - previous_reversion_factor); + } else { + reversion_factor_relative_error = std::abs((reversion_factor - previous_reversion_factor) / reversion_factor); + } + max_stress_relative_error = std::abs((max_stress - previous_max_stress) / max_stress); - if (global_number_of_cycles > 2 && (reversion_factor_relative_error > 0.001 || max_stress_relative_error > 0.001)) { + if (!damage_activation && global_number_of_cycles > 2 && !adnvance_strategy_applied && (reversion_factor_relative_error > 0.001 || max_stress_relative_error > 0.001)) { local_number_of_cycles = std::trunc(std::pow(10, std::pow(-(std::log(fatigue_reduction_factor) / B0), 1.0 / (betaf * betaf)))) + 1; } global_number_of_cycles++; local_number_of_cycles++; + new_cycle = true; max_indicator = false; min_indicator = false; previous_max_stress = max_stress; previous_min_stress = min_stress; + mCyclesToFailure = CyclesToFailure; HighCycleFatigueLawIntegrator<6>::CalculateFatigueReductionFactorAndWohlerStress(rValues.GetMaterialProperties(), max_stress, @@ -140,21 +141,43 @@ void GenericSmallStrainHighCycleFatigueLaw::CalculateMa alphat, fatigue_reduction_factor, wohler_stress); + } - this->SetNumberOfCyclesGlobal(global_number_of_cycles); - this->SetNumberOfCyclesLocal(local_number_of_cycles); - this->SetMaxDetected(max_indicator); - this->SetMinDetected(min_indicator); - this->SetFatigueReductionParameter(B0); - this->SetFatigueReductionFactor(fatigue_reduction_factor); - this->SetPreviousMaxStress(previous_max_stress); - this->SetPreviousMinStress(previous_min_stress); - this->SetWohlerStress(wohler_stress); - } - uniaxial_stress *= sign_factor; - if (r_constitutive_law_options.Is(ConstitutiveLaw::COMPUTE_CONSTITUTIVE_TENSOR)) { - this->SetValue(UNIAXIAL_STRESS, uniaxial_stress, rValues.GetProcessInfo()); + if (adnvance_strategy_applied) { + const double reversion_factor = HighCycleFatigueLawIntegrator<6>::CalculateReversionFactor(max_stress, min_stress); + double alphat; + HighCycleFatigueLawIntegrator<6>::CalculateFatigueParameters( + max_stress, + reversion_factor, + rValues.GetMaterialProperties(), + B0, + s_th, + alphat, + CyclesToFailure); + HighCycleFatigueLawIntegrator<6>::CalculateFatigueReductionFactorAndWohlerStress(rValues.GetMaterialProperties(), + max_stress, + local_number_of_cycles, + global_number_of_cycles, + B0, + s_th, + alphat, + fatigue_reduction_factor, + wohler_stress); + } + mNumberOfCyclesGlobal = global_number_of_cycles; + mNumberOfCyclesLocal = local_number_of_cycles; + mMaxDetected = max_indicator; + mMinDetected = min_indicator; + mFatigueReductionParameter = B0; + mFatigueReductionFactor = fatigue_reduction_factor; + mPreviousMaxStress = previous_max_stress; + mPreviousMinStress = previous_min_stress; + mWohlerStress = wohler_stress; + mReversionFactorRelativeError = reversion_factor_relative_error; + mMaxStressRelativeError = max_stress_relative_error; + mNewCycleIndicator = new_cycle; + mThresholdStress = s_th; } uniaxial_stress /= fatigue_reduction_factor; // Fatigue contribution @@ -166,6 +189,7 @@ void GenericSmallStrainHighCycleFatigueLaw::CalculateMa if (r_constitutive_law_options.Is(ConstitutiveLaw::COMPUTE_CONSTITUTIVE_TENSOR)) { r_constitutive_matrix *= (1.0 - damage); this->SetStressVector(r_integrated_stress_vector); + rValues.SetStressVector(r_integrated_stress_vector); } } else { // Damage case const double characteristic_length = ConstitutiveLawUtilities::CalculateCharacteristicLength(rValues.GetElementGeometry()); @@ -177,13 +201,13 @@ void GenericSmallStrainHighCycleFatigueLaw::CalculateMa threshold, rValues, characteristic_length); - // Updated Values noalias(r_integrated_stress_vector) = predictive_stress_vector; - if (r_constitutive_law_options.Is(ConstitutiveLaw::COMPUTE_CONSTITUTIVE_TENSOR)) { TConstLawIntegratorType::YieldSurfaceType::CalculateEquivalentStress(predictive_stress_vector, r_strain_vector,uniaxial_stress, rValues); this->SetStressVector(r_integrated_stress_vector); + rValues.SetStressVector(r_integrated_stress_vector); + this->SetStressVector(rValues.GetStressVector()); this->CalculateTangentTensor(rValues); } } @@ -206,7 +230,7 @@ void GenericSmallStrainHighCycleFatigueLaw::FinalizeMat //NOTE: SINCE THE ELEMENT IS IN SMALL STRAINS WE CAN USE ANY STRAIN MEASURE. HERE EMPLOYING THE CAUCHY_GREEN if (r_constitutive_law_options.IsNot( ConstitutiveLaw::USE_ELEMENT_PROVIDED_STRAIN)) { - GenericSmallStrainIsotropicDamage::CalculateValue(rValues, STRAIN, r_strain_vector); + BaseType::CalculateValue(rValues, STRAIN, r_strain_vector); } // Elastic Matrix @@ -216,6 +240,7 @@ void GenericSmallStrainHighCycleFatigueLaw::FinalizeMat array_1d predictive_stress_vector; // We compute the stress if(r_constitutive_law_options.Is(ConstitutiveLaw::COMPUTE_STRESS)) { + // Elastic Matrix this->CalculateValue(rValues, CONSTITUTIVE_MATRIX, r_constitutive_matrix); @@ -231,31 +256,82 @@ void GenericSmallStrainHighCycleFatigueLaw::FinalizeMat TConstLawIntegratorType::YieldSurfaceType::CalculateEquivalentStress(predictive_stress_vector, r_strain_vector, uniaxial_stress, rValues); this->SetValue(UNIAXIAL_STRESS, uniaxial_stress, rValues.GetProcessInfo()); - double fatigue_reduction_factor = this->GetFatigueReductionFactor(); + double sign_factor = HighCycleFatigueLawIntegrator<6>::CalculateTensionCompressionFactor(predictive_stress_vector); + uniaxial_stress *= sign_factor; + double max_stress = mMaxStress; + double min_stress = mMinStress; + bool max_indicator = mMaxDetected; + bool min_indicator = mMinDetected; + double fatigue_reduction_factor = mFatigueReductionFactor; + + HighCycleFatigueLawIntegrator<6>::CalculateMaximumAndMinimumStresses( + uniaxial_stress, + max_stress, + min_stress, + mPreviousStresses, + max_indicator, + min_indicator); + mMaxStress = max_stress; + mMinStress = min_stress; + mMaxDetected = max_indicator; + mMinDetected = min_indicator; + uniaxial_stress *= sign_factor; uniaxial_stress /= fatigue_reduction_factor; // Fatigue contribution + const double F = uniaxial_stress - threshold; if (F > tolerance) { - const double characteristic_length = ConstitutiveLawUtilities::CalculateCharacteristicLength(rValues.GetElementGeometry()); - // This routine updates the PredictiveStress to verify the yield surf - TConstLawIntegratorType::IntegrateStressVector( - predictive_stress_vector, - uniaxial_stress, - damage, - threshold, - rValues, - characteristic_length); - this->SetDamage(damage); - this->SetThreshold(uniaxial_stress); + const double characteristic_length = ConstitutiveLawUtilities::CalculateCharacteristicLength(rValues.GetElementGeometry()); + // This routine updates the PredictiveStress to verify the yield surface + TConstLawIntegratorType::IntegrateStressVector( + predictive_stress_vector, + uniaxial_stress, + damage, + threshold, + rValues, + characteristic_length); + this->SetDamage(damage); + this->SetThreshold(uniaxial_stress); + + TConstLawIntegratorType::YieldSurfaceType::CalculateEquivalentStress(predictive_stress_vector, r_strain_vector, uniaxial_stress, rValues); + } else { + predictive_stress_vector *= (1.0 - this->GetDamage()); + TConstLawIntegratorType::YieldSurfaceType::CalculateEquivalentStress(predictive_stress_vector, r_strain_vector, uniaxial_stress, rValues); } + + Vector previous_stresses = ZeroVector(2); + const Vector& r_aux_stresses = mPreviousStresses; + previous_stresses[1] = this->GetValue(UNIAXIAL_STRESS, previous_stresses[1])*sign_factor; + previous_stresses[0] = r_aux_stresses[1]; + mPreviousStresses = previous_stresses; + this->SetValue(UNIAXIAL_STRESS, uniaxial_stress, rValues.GetProcessInfo()); } - double sign_factor = HighCycleFatigueLawIntegrator<6>::CalculateTensionCompressionFactor(predictive_stress_vector); - Vector previous_stresses = ZeroVector(2); - const Vector& r_aux_stresses = this->GetPreviousStresses(); - previous_stresses[1] = this->GetValue(UNIAXIAL_STRESS, previous_stresses[1])*sign_factor; - previous_stresses[0] = r_aux_stresses[1]; - this->SetPreviousStresses(previous_stresses); +} +/***********************************************************************************/ +/***********************************************************************************/ + +template +bool GenericSmallStrainHighCycleFatigueLaw::Has(const Variable& rThisVariable) +{ + if (rThisVariable == CYCLE_INDICATOR) { + return true; + } + return false; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template +bool GenericSmallStrainHighCycleFatigueLaw::Has(const Variable& rThisVariable) +{ + if (rThisVariable == NUMBER_OF_CYCLES) { + return true; + } else if (rThisVariable == LOCAL_NUMBER_OF_CYCLES) { + return true; + } + return false; } /***********************************************************************************/ @@ -264,14 +340,27 @@ void GenericSmallStrainHighCycleFatigueLaw::FinalizeMat template bool GenericSmallStrainHighCycleFatigueLaw::Has(const Variable& rThisVariable) { - if (rThisVariable == DAMAGE || rThisVariable == UNIAXIAL_STRESS || rThisVariable == THRESHOLD) { - GenericSmallStrainIsotropicDamage::Has(rThisVariable); - } else if (rThisVariable == FATIGUE_REDUCTION_FACTOR) { + + if (rThisVariable == FATIGUE_REDUCTION_FACTOR) { return true; } else if (rThisVariable == WOHLER_STRESS) { return true; + } else if (rThisVariable == CYCLES_TO_FAILURE) { + return true; + } else if (rThisVariable == REVERSION_FACTOR_RELATIVE_ERROR) { + return true; + } else if (rThisVariable == MAX_STRESS_RELATIVE_ERROR) { + return true; + } else if (rThisVariable == MAX_STRESS) { + return true; + } else if (rThisVariable == THRESHOLD_STRESS) { + return true; + } else if (rThisVariable == PREVIOUS_CYCLE) { + return true; + } else if (rThisVariable == CYCLE_PERIOD) { + return true; } else { - return GenericSmallStrainIsotropicDamage::Has(rThisVariable); + return BaseType::Has(rThisVariable); } return false; } @@ -280,12 +369,31 @@ bool GenericSmallStrainHighCycleFatigueLaw::Has(const V /***********************************************************************************/ template -bool GenericSmallStrainHighCycleFatigueLaw::Has(const Variable& rThisVariable) +void GenericSmallStrainHighCycleFatigueLaw::SetValue( + const Variable& rThisVariable, + const bool& rValue, + const ProcessInfo& rCurrentProcessInfo + ) +{ + if (rThisVariable == CYCLE_INDICATOR) { + mNewCycleIndicator = rValue; + } +} + +/***********************************************************************************/ +/***********************************************************************************/ +template +void GenericSmallStrainHighCycleFatigueLaw::SetValue( + const Variable& rThisVariable, + const int& rValue, + const ProcessInfo& rCurrentProcessInfo + ) { if (rThisVariable == NUMBER_OF_CYCLES) { - return true; + mNumberOfCyclesGlobal = rValue; + } else if (rThisVariable == LOCAL_NUMBER_OF_CYCLES) { + mNumberOfCyclesLocal = rValue; } - return false; } /***********************************************************************************/ @@ -298,14 +406,27 @@ void GenericSmallStrainHighCycleFatigueLaw::SetValue( const ProcessInfo& rCurrentProcessInfo ) { - if (rThisVariable == DAMAGE || rThisVariable == UNIAXIAL_STRESS || rThisVariable == THRESHOLD) { - GenericSmallStrainIsotropicDamage::SetValue(rThisVariable, rValue, rCurrentProcessInfo); - } else if (rThisVariable == FATIGUE_REDUCTION_FACTOR) { + + if (rThisVariable == FATIGUE_REDUCTION_FACTOR) { mFatigueReductionFactor = rValue; } else if (rThisVariable == WOHLER_STRESS) { mWohlerStress = rValue; + } else if (rThisVariable == CYCLES_TO_FAILURE) { + mCyclesToFailure = rValue; + } else if (rThisVariable == REVERSION_FACTOR_RELATIVE_ERROR) { + mReversionFactorRelativeError = rValue; + } else if (rThisVariable == MAX_STRESS_RELATIVE_ERROR) { + mMaxStressRelativeError = rValue; + } else if (rThisVariable == MAX_STRESS) { + mMaxStress = rValue; + } else if (rThisVariable == THRESHOLD_STRESS) { + mThresholdStress = rValue; + } else if (rThisVariable == PREVIOUS_CYCLE) { + mPreviousCycleTime = rValue; + } else if (rThisVariable == CYCLE_PERIOD) { + mPeriod = rValue; } else { - return GenericSmallStrainIsotropicDamage::SetValue(rThisVariable, rValue, rCurrentProcessInfo); + return BaseType::SetValue(rThisVariable, rValue, rCurrentProcessInfo); } } @@ -313,14 +434,32 @@ void GenericSmallStrainHighCycleFatigueLaw::SetValue( /***********************************************************************************/ template -void GenericSmallStrainHighCycleFatigueLaw::SetValue( +bool& GenericSmallStrainHighCycleFatigueLaw::GetValue( + const Variable& rThisVariable, + bool& rValue + ) +{ + if (rThisVariable == CYCLE_INDICATOR) { + rValue = mNewCycleIndicator; + } + return rValue; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template +int& GenericSmallStrainHighCycleFatigueLaw::GetValue( const Variable& rThisVariable, - const int& rValue + int& rValue ) { if (rThisVariable == NUMBER_OF_CYCLES) { - mNumberOfCyclesGlobal = rValue; + rValue = mNumberOfCyclesGlobal; + } else if (rThisVariable == LOCAL_NUMBER_OF_CYCLES) { + rValue = mNumberOfCyclesLocal; } + return rValue; } /***********************************************************************************/ @@ -332,14 +471,27 @@ double& GenericSmallStrainHighCycleFatigueLaw::GetValue double& rValue ) { - if (rThisVariable == DAMAGE || rThisVariable == UNIAXIAL_STRESS || rThisVariable == THRESHOLD) { - GenericSmallStrainIsotropicDamage::GetValue(rThisVariable, rValue); - } else if (rThisVariable == FATIGUE_REDUCTION_FACTOR) { + + if (rThisVariable == FATIGUE_REDUCTION_FACTOR) { rValue = mFatigueReductionFactor; } else if (rThisVariable == WOHLER_STRESS) { rValue = mWohlerStress; + } else if (rThisVariable == CYCLES_TO_FAILURE) { + rValue = mCyclesToFailure; + } else if (rThisVariable == REVERSION_FACTOR_RELATIVE_ERROR) { + rValue = mReversionFactorRelativeError; + } else if (rThisVariable == MAX_STRESS_RELATIVE_ERROR) { + rValue = mMaxStressRelativeError; + } else if (rThisVariable == MAX_STRESS) { + rValue = mMaxStress; + } else if (rThisVariable == THRESHOLD_STRESS) { + rValue = mThresholdStress; + } else if (rThisVariable == PREVIOUS_CYCLE) { + rValue = mPreviousCycleTime; + } else if (rThisVariable == CYCLE_PERIOD) { + rValue = mPeriod; } else { - return GenericSmallStrainIsotropicDamage::GetValue(rThisVariable, rValue); + return BaseType::GetValue(rThisVariable, rValue); } return rValue; } @@ -348,15 +500,17 @@ double& GenericSmallStrainHighCycleFatigueLaw::GetValue /***********************************************************************************/ template -int& GenericSmallStrainHighCycleFatigueLaw::GetValue( - const Variable& rThisVariable, - int& rValue +double& GenericSmallStrainHighCycleFatigueLaw::CalculateValue( + ConstitutiveLaw::Parameters& rParameterValues, + const Variable& rThisVariable, + double& rValue ) { - if (rThisVariable == NUMBER_OF_CYCLES) { - rValue = mNumberOfCyclesGlobal; + if (rThisVariable == DAMAGE || rThisVariable == UNIAXIAL_STRESS || rThisVariable == THRESHOLD) { + return BaseType::CalculateValue(rParameterValues, rThisVariable, rValue); + } else { + return this->GetValue(rThisVariable, rValue); } - return rValue; } /***********************************************************************************/ diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_high_cycle_fatigue_law.h b/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_high_cycle_fatigue_law.h index af76e3f3e42c..3292d4b401e8 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_high_cycle_fatigue_law.h +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_high_cycle_fatigue_law.h @@ -77,7 +77,7 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) GenericSmallStrainHighCycleFatig static constexpr double tolerance = std::numeric_limits::epsilon(); /// Definition of the base class - //typedef typename GenericSmallStrainIsotropicDamage BaseType; + typedef GenericSmallStrainIsotropicDamage BaseType; ///@} ///@name Life Cycle @@ -158,6 +158,13 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) GenericSmallStrainHighCycleFatig */ void CalculateMaterialResponseCauchy(ConstitutiveLaw::Parameters& rValues) override; + /** + * returns whether this constitutive Law has specified variable + * @param rThisVariable the variable to be checked for + * @return true if the variable is defined in the constitutive law + */ + bool Has(const Variable& rThisVariable) override; + /** * @brief Returns whether this constitutive Law has specified variable (double) * @param rThisVariable the variable to be checked for @@ -174,35 +181,48 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) GenericSmallStrainHighCycleFatig bool Has(const Variable& rThisVariable) override; /** - * @brief Sets the value of a specified variable (double) - * @param rVariable the variable to be returned - * @param rValue new value of the specified variable + * @brief Sets the value of a specified variable (bool) + * @param rThisVariable the variable to be returned + * @param Value new value of the specified variable * @param rCurrentProcessInfo the process info */ void SetValue( - const Variable& rThisVariable, - const double& rValue, + const Variable& rThisVariable, + const bool& Value, const ProcessInfo& rCurrentProcessInfo) override; /** * @brief Sets the value of a specified variable (integer) - * @param rVariable the variable to be returned + * @param rThisVariable the variable to be returned * @param rValue new value of the specified variable + * @param rCurrentProcessInfo the process info */ using ConstitutiveLaw::SetValue; void SetValue( const Variable& rThisVariable, - const int& rValue); + const int& rValue, + const ProcessInfo& rCurrentProcessInfo) override; /** - * @brief Returns the value of a specified variable (double) + * @brief Sets the value of a specified variable (double) + * @param rVariable the variable to be returned + * @param rValue new value of the specified variable + * @param rCurrentProcessInfo the process info + */ + void SetValue( + const Variable& rThisVariable, + const double& rValue, + const ProcessInfo& rCurrentProcessInfo) override; + + /** + * returns the value of a specified variable * @param rThisVariable the variable to be returned * @param rValue a reference to the returned value - * @return rValue output: the value of the specified variable + * @param rValue output: the value of the specified variable */ - double& GetValue( - const Variable& rThisVariable, - double& rValue) override; + bool& GetValue( + const Variable& rThisVariable, + bool& rValue) override; /** * @brief Returns the value of a specified variable (integer) @@ -216,12 +236,26 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) GenericSmallStrainHighCycleFatig int& rValue) override; /** - * @brief If the CL requires to initialize the material response, called by the element in InitializeSolutionStep. + * @brief Returns the value of a specified variable (double) + * @param rThisVariable the variable to be returned + * @param rValue a reference to the returned value + * @return rValue output: the value of the specified variable */ - bool RequiresFinalizeMaterialResponse() override - { - return true; - } + double& GetValue( + const Variable& rThisVariable, + double& rValue) override; + + /** + * @brief Returns the value of a specified variable (double) + * @param rParameterValues the needed parameters for the CL calculation + * @param rThisVariable the variable to be returned + * @param rValue a reference to the returned value + * @param rValue output: the value of the specified variable + */ + double& CalculateValue( + ConstitutiveLaw::Parameters& rParameterValues, + const Variable& rThisVariable, + double& rValue) override; /** * @brief Returns the value of a specified variable (matrix) @@ -312,45 +346,8 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) GenericSmallStrainHighCycleFatig ///@} ///@name Access ///@{ - double GetFatigueReductionFactor() {return mFatigueReductionFactor;} - void SetFatigueReductionFactor(const double toFred) {mFatigueReductionFactor = toFred;} - - Vector GetPreviousStresses() {return mPreviousStresses;} - void SetPreviousStresses(const Vector toPreviousStresses) {mPreviousStresses = toPreviousStresses;} - - double GetMaxStress() {return mMaxStress;} - void SetMaxStress(const double toMaxStress) {mMaxStress = toMaxStress;} - - double GetMinStress() {return mMinStress;} - void SetMinStress(const double toMinStress) {mMinStress = toMinStress;} - - double GetPreviousMaxStress() {return mPreviousMaxStress;} - void SetPreviousMaxStress(const double toPreviousMaxStress) {mPreviousMaxStress = toPreviousMaxStress;} - - double GetPreviousMinStress() {return mPreviousMinStress;} - void SetPreviousMinStress(const double toPreviousMinStress) {mPreviousMinStress = toPreviousMinStress;} - - unsigned int GetNumberOfCyclesGlobal() {return mNumberOfCyclesGlobal;} - void SetNumberOfCyclesGlobal(const unsigned int toCyclesGlobal) {mNumberOfCyclesGlobal = toCyclesGlobal;} - - unsigned int GetNumberOfCyclesLocal() {return mNumberOfCyclesLocal;} - void SetNumberOfCyclesLocal(const unsigned int toCyclesLocal) {mNumberOfCyclesLocal = toCyclesLocal;} - - double GetFatigueReductionParameter() {return mFatigueReductionParameter;} - void SetFatigueReductionParameter(const double toFatigueReductionParameter) {mFatigueReductionParameter = toFatigueReductionParameter;} - Vector GetStressVector() {return mStressVector;} void SetStressVector(const Vector toStressVector) {mStressVector = toStressVector;} - - bool GetMaxDetected() {return mMaxDetected;} - void SetMaxDetected(const bool toMaxDetected){mMaxDetected = toMaxDetected;} - - bool GetMinDetected() {return mMinDetected;} - void SetMinDetected(const bool toMinDetected){mMinDetected = toMinDetected;} - - double GetWohlerStress() {return mWohlerStress;} - void SetWohlerStress(const double toWohlerStress) {mWohlerStress = toWohlerStress;} - ///@} ///@name Member Variables ///@{ @@ -367,6 +364,13 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) GenericSmallStrainHighCycleFatig bool mMaxDetected = false; // Maximum's indicator in the current cycle bool mMinDetected = false; // Minimum's indicator in the current cycle double mWohlerStress = 1.0; // Normalised Wohler stress required for building the life prediction curves (SN curves) + double mThresholdStress = 0.0; // Endurance limit of the fatigue model. + double mReversionFactorRelativeError = 0.0; // Relative error of the R = Smin / Smax between cycles inducing recalculation of Nlocal and advanciing process. + double mMaxStressRelativeError = 0.0; // Relative error of Smax between cycles inducing recalculation of Nlocal and advanciing process. + bool mNewCycleIndicator = false; // New cycle identifier required for the advancing process. + double mCyclesToFailure = 0.0; // Nf. Required for the advanciing process. + double mPreviousCycleTime = 0.0; // Instanced variable used in the advanciing process for the conversion between time and number of cycles. + double mPeriod = 0.0; // Instanced variable used in the advanciing process for the conversion between time and number of cycles. ///@} ///@name Private Operators @@ -400,6 +404,13 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) GenericSmallStrainHighCycleFatig rSerializer.save("MaxDetected", mMaxDetected); rSerializer.save("MinDetected", mMinDetected); rSerializer.save("WohlerStress", mWohlerStress); + rSerializer.save("ThresholdStress", mThresholdStress); + rSerializer.save("ReversionFactorRelativeError", mReversionFactorRelativeError); + rSerializer.save("MaxStressRelativeError", mMaxStressRelativeError); + rSerializer.save("NewCycleIndicator", mNewCycleIndicator); + rSerializer.save("CyclesToFailure", mCyclesToFailure); + rSerializer.save("PreviousCycleTime", mPreviousCycleTime); + rSerializer.save("Period", mPeriod); } void load(Serializer &rSerializer) override @@ -418,10 +429,17 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) GenericSmallStrainHighCycleFatig rSerializer.load("MaxDetected", mMaxDetected); rSerializer.load("MinDetected", mMinDetected); rSerializer.load("WohlerStress", mWohlerStress); + rSerializer.load("ThresholdStress", mThresholdStress); + rSerializer.load("ReversionFactorRelativeError", mReversionFactorRelativeError); + rSerializer.load("MaxStressRelativeError", mMaxStressRelativeError); + rSerializer.load("NewCycleIndicator", mNewCycleIndicator); + rSerializer.load("CyclesToFailure", mCyclesToFailure); + rSerializer.load("PreviousCycleTime", mPreviousCycleTime); + rSerializer.load("Period", mPeriod); } ///@} }; // Class GenericYieldSurface } // namespace Kratos -#endif +#endif \ No newline at end of file diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_isotropic_damage.cpp b/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_isotropic_damage.cpp index f48a5ed5ed79..9a3b857809a9 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_isotropic_damage.cpp +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_isotropic_damage.cpp @@ -100,12 +100,15 @@ void GenericSmallStrainIsotropicDamage::CalculateMateri BaseType::CalculateCauchyGreenStrain( rValues, r_strain_vector); } + this->template AddInitialStrainVectorContribution(r_strain_vector); + // Converged values double threshold = this->GetThreshold(); double damage = this->GetDamage(); - // S0 = C:E + // S0 = C:(E-E0) + S0 array_1d predictive_stress_vector = prod(r_constitutive_matrix, r_strain_vector); + this->template AddInitialStressVectorContribution>(predictive_stress_vector); // Initialize Plastic Parameters double uniaxial_stress; @@ -255,12 +258,15 @@ void GenericSmallStrainIsotropicDamage::FinalizeMateria BaseType::CalculateCauchyGreenStrain( rValues, r_strain_vector); } + this->template AddInitialStrainVectorContribution(r_strain_vector); + // Converged values double threshold = this->GetThreshold(); double damage = this->GetDamage(); - // S0 = C:E + // S0 = C:(E-E0) + S0 array_1d predictive_stress_vector = prod(r_constitutive_matrix, r_strain_vector); + this->template AddInitialStressVectorContribution>(predictive_stress_vector); // Initialize Plastic Parameters double uniaxial_stress; @@ -277,7 +283,7 @@ void GenericSmallStrainIsotropicDamage::FinalizeMateria threshold, rValues, characteristic_length); mDamage = damage; - mThreshold = uniaxial_stress; + mThreshold = uniaxial_stress; TConstLawIntegratorType::YieldSurfaceType::CalculateEquivalentStress(predictive_stress_vector, r_strain_vector, uniaxial_stress, rValues); this->SetValue(UNIAXIAL_STRESS, uniaxial_stress, rValues.GetProcessInfo()); diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_isotropic_plasticity.cpp b/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_isotropic_plasticity.cpp index 6b3ba1a161de..9606bc531b47 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_isotropic_plasticity.cpp +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/generic_small_strain_isotropic_plasticity.cpp @@ -87,14 +87,17 @@ void GenericSmallStrainIsotropicPlasticity::CalculateMa if (r_constitutive_law_options.IsNot( ConstitutiveLaw::USE_ELEMENT_PROVIDED_STRAIN ) ) { BaseType::CalculateCauchyGreenStrain( rValues, r_strain_vector); } + this->template AddInitialStrainVectorContribution(r_strain_vector); if (r_constitutive_law_options.Is( ConstitutiveLaw::COMPUTE_STRESS) || r_constitutive_law_options.Is( ConstitutiveLaw::COMPUTE_CONSTITUTIVE_TENSOR)) { Vector& r_stress_vector = rValues.GetStressVector(); if (r_constitutive_law_options.Is( ConstitutiveLaw::COMPUTE_CONSTITUTIVE_TENSOR)) { BaseType::CalculateElasticMatrix( r_constitutive_matrix, rValues); noalias(r_stress_vector) = prod( r_constitutive_matrix, r_strain_vector); + this->template AddInitialStressVectorContribution(r_stress_vector); } else { BaseType::CalculatePK2Stress( r_strain_vector, r_stress_vector, rValues); + this->template AddInitialStressVectorContribution(r_stress_vector); } } } else { // We check for plasticity @@ -106,6 +109,8 @@ void GenericSmallStrainIsotropicPlasticity::CalculateMa BaseType::CalculateCauchyGreenStrain( rValues, r_strain_vector); } + this->template AddInitialStrainVectorContribution(r_strain_vector); + // We compute the stress or the constitutive matrix if (r_constitutive_law_options.Is( ConstitutiveLaw::COMPUTE_STRESS) || r_constitutive_law_options.Is( ConstitutiveLaw::COMPUTE_CONSTITUTIVE_TENSOR)) { @@ -117,11 +122,12 @@ void GenericSmallStrainIsotropicPlasticity::CalculateMa BoundedArrayType predictive_stress_vector; if (r_constitutive_law_options.Is( ConstitutiveLaw::U_P_LAW)) { - predictive_stress_vector = rValues.GetStressVector(); + noalias(predictive_stress_vector) = rValues.GetStressVector(); } else { - // S0 = Elastic stress with strain (E-Ep) + // S0 = Elastic stress with strain (E-Ep) + S0 Vector aux_stress = ZeroVector(VoigtSize); BaseType::CalculatePK2Stress(r_strain_vector - plastic_strain, aux_stress, rValues); + this->template AddInitialStressVectorContribution(aux_stress); noalias(predictive_stress_vector) = aux_stress; } @@ -295,6 +301,8 @@ void GenericSmallStrainIsotropicPlasticity::FinalizeMat BaseType::CalculateCauchyGreenStrain( rValues, r_strain_vector); } + this->template AddInitialStrainVectorContribution(r_strain_vector); + // We compute the stress // Elastic Matrix this->CalculateElasticMatrix(r_constitutive_matrix, rValues); @@ -306,10 +314,11 @@ void GenericSmallStrainIsotropicPlasticity::FinalizeMat BoundedArrayType predictive_stress_vector; if (r_constitutive_law_options.Is( ConstitutiveLaw::U_P_LAW)) { - predictive_stress_vector = rValues.GetStressVector(); + noalias(predictive_stress_vector) = rValues.GetStressVector(); } else { - // S0 = r_constitutive_matrix:(E-Ep) - predictive_stress_vector = prod(r_constitutive_matrix, r_strain_vector - plastic_strain); + // Spred = r_constitutive_matrix:(E-Ep) + S0 + noalias(predictive_stress_vector) = prod(r_constitutive_matrix, r_strain_vector - plastic_strain); + this->template AddInitialStressVectorContribution(predictive_stress_vector); } // Initialize Plastic Parameters diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/small_strain_isotropic_damage_3d.cpp b/applications/ConstitutiveLawsApplication/custom_constitutive/small_strain_isotropic_damage_3d.cpp index 5dc8c0631cdb..32f74cec722b 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/small_strain_isotropic_damage_3d.cpp +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/small_strain_isotropic_damage_3d.cpp @@ -54,12 +54,12 @@ SmallStrainIsotropicDamage3D::~SmallStrainIsotropicDamage3D() bool SmallStrainIsotropicDamage3D::Has(const Variable& rThisVariable) { if(rThisVariable == STRAIN_ENERGY){ - // explicitly returning "false", so we know we must call CalculateValue(...) + // explicitly returning "false", so the element calls CalculateValue(...) return false; - } - if(rThisVariable == DAMAGE_VARIABLE){ - // explicitly returning "false", so we know we must call CalculateValue(...) + } else if(rThisVariable == DAMAGE_VARIABLE){ + // explicitly returning "false", so the element calls CalculateValue(...) return false; + } return false; @@ -72,6 +72,9 @@ bool SmallStrainIsotropicDamage3D::Has(const Variable& rThisVariable) { if(rThisVariable == INTERNAL_VARIABLES){ return true; + } else if(rThisVariable == STRAIN){ + // explicitly returning "false", so the element calls CalculateValue(...) + return false; } return false; @@ -124,59 +127,49 @@ void SmallStrainIsotropicDamage3D::InitializeMaterial( //************************************************************************************ //************************************************************************************ -void SmallStrainIsotropicDamage3D::InitializeMaterialResponseCauchy(ConstitutiveLaw::Parameters& rValues) -{ -} - -//************************************************************************************ -//************************************************************************************ - -void SmallStrainIsotropicDamage3D::FinalizeMaterialResponseCauchy(Parameters& rValues) +void SmallStrainIsotropicDamage3D::FinalizeMaterialResponseCauchy( + ConstitutiveLaw::Parameters& rParametersValues) { Vector internal_variables(1); - this->CalculateStressResponse(rValues, internal_variables); + this->CalculateStressResponse(rParametersValues, internal_variables); mStrainVariable = internal_variables[0]; } //************************************************************************************ //************************************************************************************ -void SmallStrainIsotropicDamage3D::CalculateMaterialResponsePK2(Parameters& rValues) +void SmallStrainIsotropicDamage3D::CalculateMaterialResponsePK2( + ConstitutiveLaw::Parameters& rParametersValues) { Vector internal_variables(1); - this->CalculateStressResponse(rValues, internal_variables); + CalculateStressResponse(rParametersValues, internal_variables); } //************************************************************************************ //************************************************************************************ void SmallStrainIsotropicDamage3D::CalculateStressResponse( - Parameters &rValues, - Vector& rInternalVariables) + ConstitutiveLaw::Parameters& rParametersValues, + Vector& rInternalVariables) { double strain_variable = mStrainVariable; - const Properties& rMaterialProperties = rValues.GetMaterialProperties(); - Flags & r_constitutive_law_options = rValues.GetOptions(); - Vector& r_strain_vector = rValues.GetStrainVector(); - if (rValues.GetProcessInfo().Has(INITIAL_STRAIN)) { - noalias(r_strain_vector) += rValues.GetProcessInfo()[INITIAL_STRAIN]; - } - - if( r_constitutive_law_options.IsNot( ConstitutiveLaw::USE_ELEMENT_PROVIDED_STRAIN )) { - //this->CalculateValue(rValues, STRAIN, r_strain_vector); - } + const Properties& r_material_properties = rParametersValues.GetMaterialProperties(); + Flags& r_constitutive_law_options = rParametersValues.GetOptions(); + Vector& r_strain_vector = rParametersValues.GetStrainVector(); + CalculateValue(rParametersValues, STRAIN, r_strain_vector); // If we compute the tangent moduli or the stress if( r_constitutive_law_options.Is( ConstitutiveLaw::COMPUTE_STRESS ) || r_constitutive_law_options.Is( ConstitutiveLaw::COMPUTE_CONSTITUTIVE_TENSOR )) { - Vector& r_stress_vector = rValues.GetStressVector(); - Matrix& r_constitutive_matrix = rValues.GetConstitutiveMatrix(); - CalculateElasticMatrix(r_constitutive_matrix, rValues); + Vector& r_stress_vector = rParametersValues.GetStressVector(); + Matrix& r_constitutive_matrix = rParametersValues.GetConstitutiveMatrix(); + CalculateElasticMatrix(r_constitutive_matrix, rParametersValues); noalias(r_stress_vector) = prod(r_constitutive_matrix, r_strain_vector); - // Auxiliary stress vector to allow derived models (e.g. traction-only damage) to set - // a different value of r_stress_vector_pos with ComputePositiveStressVector function - // In the symmetric model, ComputePositiveStressVector does not do anything. + // Auxiliary stress vector to allow derived models (e.g. traction-only damage) + // to set the value of r_stress_vector_pos with the ComputePositiveStressVector + // function. + // In the symmetric model, ComputePositiveStressVector does nothing. Vector r_stress_vector_pos = r_stress_vector; ComputePositiveStressVector(r_stress_vector_pos, r_stress_vector); @@ -187,7 +180,7 @@ void SmallStrainIsotropicDamage3D::CalculateStressResponse( { // ELASTIC strain_variable = mStrainVariable; - const double stress_variable = EvaluateHardeningLaw(strain_variable, rMaterialProperties); + const double stress_variable = EvaluateHardeningLaw(strain_variable, r_material_properties); const double damage_variable = 1. - stress_variable / strain_variable; r_constitutive_matrix *= (1 - damage_variable); r_stress_vector *= (1 - damage_variable); @@ -196,9 +189,9 @@ void SmallStrainIsotropicDamage3D::CalculateStressResponse( { // INELASTIC strain_variable = strain_norm; - const double stress_variable = EvaluateHardeningLaw(strain_variable, rMaterialProperties); + const double stress_variable = EvaluateHardeningLaw(strain_variable, r_material_properties); const double damage_variable = 1. - stress_variable / strain_variable; - const double hardening_modulus = EvaluateHardeningModulus(strain_variable, rMaterialProperties); + const double hardening_modulus = EvaluateHardeningModulus(strain_variable, r_material_properties); const double damage_rate = (stress_variable - hardening_modulus * strain_variable) / (strain_variable * strain_variable * strain_variable); r_constitutive_matrix *= (1. - damage_variable); @@ -216,6 +209,7 @@ void SmallStrainIsotropicDamage3D::CalculateStressResponse( void SmallStrainIsotropicDamage3D::ComputePositiveStressVector( Vector& rStressVectorPos, Vector& rStressVector) { + // explicit pass for the symmetric model } //************************************************************************************ @@ -237,7 +231,7 @@ double SmallStrainIsotropicDamage3D::EvaluateHardeningModulus( const double q1 = inf_yield_stress / std::sqrt(young_modulus); // stress_variable_inf const double r1 = r0 + (q1 - q0) / H0; - if (r < r0) + if (r < r0) return 0.; if (r >= r0 && r < r1) return H0; @@ -249,8 +243,8 @@ double SmallStrainIsotropicDamage3D::EvaluateHardeningModulus( //************************************************************************************ double SmallStrainIsotropicDamage3D::EvaluateHardeningLaw( - double r, - const Properties &rMaterialProperties) + double r, + const Properties &rMaterialProperties) { const double yield_stress = rMaterialProperties[YIELD_STRESS]; const double inf_yield_stress = rMaterialProperties[INFINITY_YIELD_STRESS]; @@ -275,31 +269,36 @@ double SmallStrainIsotropicDamage3D::EvaluateHardeningLaw( //************************************************************************************ double& SmallStrainIsotropicDamage3D::CalculateValue( - Parameters& rValues, + ConstitutiveLaw::Parameters& rParametersValues, const Variable& rThisVariable, double& rValue ) { if (rThisVariable == STRAIN_ENERGY){ - Vector& r_strain_vector = rValues.GetStrainVector(); - if (rValues.GetProcessInfo().Has(INITIAL_STRAIN)) { - noalias(r_strain_vector) += rValues.GetProcessInfo()[INITIAL_STRAIN]; - } - const Properties& rMaterialProperties = rValues.GetMaterialProperties(); + Vector& r_strain_vector = rParametersValues.GetStrainVector(); + this->CalculateValue(rParametersValues, STRAIN, r_strain_vector); + const Properties& r_material_properties = rParametersValues.GetMaterialProperties(); Matrix constitutive_matrix; - CalculateElasticMatrix(constitutive_matrix, rValues); - const double stress_like_variable = EvaluateHardeningLaw(mStrainVariable, rMaterialProperties); + CalculateElasticMatrix(constitutive_matrix, rParametersValues); + const double stress_like_variable = EvaluateHardeningLaw( + mStrainVariable, + r_material_properties); const double damage_variable = 1. - stress_like_variable / mStrainVariable; rValue = 0.5 * ((1. - damage_variable) * inner_prod(r_strain_vector, - prod(constitutive_matrix, r_strain_vector))); - } + prod(constitutive_matrix, r_strain_vector))); - if (rThisVariable == DAMAGE_VARIABLE){ - const Properties& rMaterialProperties = rValues.GetMaterialProperties(); - const double stress_like_variable = EvaluateHardeningLaw(mStrainVariable, rMaterialProperties); + } else if (rThisVariable == DAMAGE_VARIABLE){ + const Properties& r_material_properties = rParametersValues.GetMaterialProperties(); + const double stress_like_variable = EvaluateHardeningLaw( + mStrainVariable, + r_material_properties); rValue = 1. - stress_like_variable / mStrainVariable; + + } else { + ElasticIsotropic3D::CalculateValue(rParametersValues, rThisVariable, rValue); + } return(rValue); @@ -308,6 +307,20 @@ double& SmallStrainIsotropicDamage3D::CalculateValue( //************************************************************************************ //************************************************************************************ +Vector& SmallStrainIsotropicDamage3D::CalculateValue( + ConstitutiveLaw::Parameters& rParametersValues, + const Variable& rThisVariable, + Vector& rValue + ) +{ + //Explicitly having STRAIN and INITAL_STRAIN_VECTOR calculated in base class + ElasticIsotropic3D::CalculateValue(rParametersValues, rThisVariable, rValue); + return(rValue); +} + +//************************************************************************************ +//************************************************************************************ + void SmallStrainIsotropicDamage3D::GetLawFeatures(Features& rFeatures) { rFeatures.mOptions.Set(THREE_DIMENSIONAL_LAW); diff --git a/applications/ConstitutiveLawsApplication/custom_constitutive/small_strain_isotropic_damage_3d.h b/applications/ConstitutiveLawsApplication/custom_constitutive/small_strain_isotropic_damage_3d.h index d370a92fbf85..b2f3607df1f6 100644 --- a/applications/ConstitutiveLawsApplication/custom_constitutive/small_strain_isotropic_damage_3d.h +++ b/applications/ConstitutiveLawsApplication/custom_constitutive/small_strain_isotropic_damage_3d.h @@ -56,7 +56,6 @@ namespace Kratos */ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D : public ElasticIsotropic3D - { public: @@ -66,7 +65,7 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D typedef ConstitutiveLaw BaseType; typedef std::size_t SizeType; - // Counted pointer of LinearIsotropicDamage3DLaw + // Counted pointer KRATOS_CLASS_POINTER_DEFINITION(SmallStrainIsotropicDamage3D); ///@} @@ -79,12 +78,12 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D SmallStrainIsotropicDamage3D(); /** - * @brief Default constructor. + * @brief Copy constructor. */ SmallStrainIsotropicDamage3D(const SmallStrainIsotropicDamage3D& rOther); /** - * @brief Default constructor. + * @brief Destructor. */ ~SmallStrainIsotropicDamage3D() override; @@ -116,13 +115,13 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D bool Has(const Variable& rThisVariable) override; /** - * @brief Returns whether this constitutive Law has specified variable (double) + * @brief Returns whether this constitutive Law has specified variable (Vector) * @param rThisVariable the variable to be checked for * @return true if the variable is defined in the constitutive law */ bool Has(const Variable& rThisVariable) override; - /** + /** * @brief Returns the value of a specified variable (Vector) * @param rThisVariable the variable to be returned * @param rValue a reference to the returned value @@ -133,10 +132,10 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D Vector& rValue ) override; - /** - * @brief Returns the value of a specified variable (Vector) - * @param rThisVariable the variable requested - * @param rValue new value of the specified variable + /** + * @brief Sets the value of a specified variable (Vector) + * @param rThisVariable The variable to be returned + * @param rValue New value of the specified variable * @param rCurrentProcessInfo the process info */ void SetValue( @@ -157,7 +156,15 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D const Vector& rShapeFunctionsValues) override; /** - * @brief Computes the material response in terms of 2nd Piola-Kirchhoff stresses and constitutive tensor + * @brief This method computes the stress and constitutive tensor + * @param rValues The norm of the deviation stress + * @param rStrainVariable + */ + void CalculateStressResponse(ConstitutiveLaw::Parameters& rValues, + Vector& rInternalVariables) override; + + /** + * @brief Computes the material response in terms of 2nd Piola-Kirchhoff stress * @param rValues The specific parameters of the current constitutive law * @see Parameters */ @@ -165,7 +172,7 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D /** * @brief Indicates if this CL requires initialization of the material response, - * called by the element in InitializeSolutionStep. + * called by the element in InitializeMaterialResponse. */ bool RequiresInitializeMaterialResponse() override { @@ -173,16 +180,8 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D } /** - * @brief Initialize the material response in terms of Cauchy stresses - * @param rValues The specific parameters of the current constitutive law - * @see Parameters - */ - void InitializeMaterialResponseCauchy(ConstitutiveLaw::Parameters& rValues) override; - - /** - * @brief Indicates if this CL requires finalization step the material - * response (e.g. update of the internal variables), called by the element - * in FinalizeSolutionStep. + * @brief Indicates if this CL requires finalization of the material response, + * called by the element in FinalizeMaterialResponse. */ bool RequiresFinalizeMaterialResponse() override { @@ -197,7 +196,7 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D void FinalizeMaterialResponseCauchy(Parameters& rValues) override; /** - * @brief calculates the value of a specified variable + * @brief calculates the value of a specified variable (double) * @param rValues the needed parameters for the CL calculation * @param rThisVariable the variable to be returned * @param rValue a reference to the returned value @@ -207,6 +206,17 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D const Variable& rThisVariable, double& rValue) override; + /** + * @brief calculates the value of a specified variable (Vector) + * @param rValues the needed parameters for the CL calculation + * @param rThisVariable the variable to be returned + * @param rValue a reference to the returned value + * @return rValue output: the value of the specified variable + */ + Vector& CalculateValue(Parameters& rValues, + const Variable& rThisVariable, + Vector& rValue) override; + /** * @brief This function provides the place to perform checks on the completeness of the input. * @details It is designed to be called only once (or anyway, not often) typically at the beginning @@ -233,13 +243,6 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D rOStream << "Small Strain Isotropic Damage 3D constitutive law\n"; }; - /** - * @brief This method computes the stress and constitutive tensor - * @param rValues The norm of the deviation stress - * @param rStrainVariable - */ - void CalculateStressResponse(ConstitutiveLaw::Parameters& rValues, Vector& rInternalVariables) override; - protected: ///@name Protected static Member Variables @@ -322,6 +325,6 @@ class KRATOS_API(CONSTITUTIVE_LAWS_APPLICATION) SmallStrainIsotropicDamage3D void load(Serializer& rSerializer) override; -}; // class LinearIsotropicDamage3DLaw +}; // class SmallStrainIsotropicDamage3D } // namespace Kratos #endif diff --git a/applications/ConstitutiveLawsApplication/custom_python/constitutive_laws_python_application.cpp b/applications/ConstitutiveLawsApplication/custom_python/constitutive_laws_python_application.cpp index b63a01be7f15..7630210b388f 100644 --- a/applications/ConstitutiveLawsApplication/custom_python/constitutive_laws_python_application.cpp +++ b/applications/ConstitutiveLawsApplication/custom_python/constitutive_laws_python_application.cpp @@ -41,6 +41,24 @@ PYBIND11_MODULE(KratosConstitutiveLawsApplication,m) ; AddCustomConstitutiveLawsToPython(m); + + // Constitutive laws variables + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, HIGH_CYCLE_FATIGUE_COEFFICIENTS) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, FATIGUE_REDUCTION_FACTOR) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, NUMBER_OF_CYCLES) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, LOCAL_NUMBER_OF_CYCLES) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, WOHLER_STRESS) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, REVERSION_FACTOR_RELATIVE_ERROR) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, MAX_STRESS_RELATIVE_ERROR) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, MAX_STRESS) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, THRESHOLD_STRESS) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, CYCLE_INDICATOR) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, CYCLES_TO_FAILURE) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, TIME_INCREMENT) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, DAMAGE_ACTIVATION) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, PREVIOUS_CYCLE); + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, CYCLE_PERIOD) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, ADVANCE_STRATEGY_APPLIED); } } // namespace Python. diff --git a/applications/ConstitutiveLawsApplication/tests/cpp_tests/test_solid_static_sensitivity.cpp b/applications/ConstitutiveLawsApplication/tests/cpp_tests/test_solid_static_sensitivity.cpp index 29e2c1a6bd43..b96853557b15 100644 --- a/applications/ConstitutiveLawsApplication/tests/cpp_tests/test_solid_static_sensitivity.cpp +++ b/applications/ConstitutiveLawsApplication/tests/cpp_tests/test_solid_static_sensitivity.cpp @@ -40,7 +40,7 @@ namespace Kratos namespace { namespace test_solid_static_sensitivity_cpp -{ // cotire unity guard +{ // unity build unity guard using SparseSpaceType = TUblasSparseSpace; using LocalSpaceType = TUblasDenseSpace; using LinearSolverType = LinearSolver; @@ -245,7 +245,7 @@ KRATOS_TEST_CASE_IN_SUITE(TotalLagrangian2D4_SaintVenantPlaneStress_StaticSensit namespace { namespace test_solid_static_sensitivity_cpp -{ // cotire unity guard +{ // unity build unity guard AdjointResponseFunction::Pointer ResponseFunctionFactory(ModelPart* pModelPart, unsigned ResponseNodeId) { Parameters params{R"({"traced_dof": "DISPLACEMENT", "direction": [0.0,1.0,0.0], "gradient_mode": "semi_analytic", "step_size": 1e-2})"}; diff --git a/applications/ConstitutiveLawsApplication/tests/cpp_tests/test_solid_transient_sensitivity.cpp b/applications/ConstitutiveLawsApplication/tests/cpp_tests/test_solid_transient_sensitivity.cpp index a163569124da..93a6166f2b1d 100644 --- a/applications/ConstitutiveLawsApplication/tests/cpp_tests/test_solid_transient_sensitivity.cpp +++ b/applications/ConstitutiveLawsApplication/tests/cpp_tests/test_solid_transient_sensitivity.cpp @@ -42,7 +42,7 @@ namespace Kratos namespace { namespace test_solid_transient_sensitivity_cpp -{ // cotire unity guard +{ // unity build unity guard struct PrimalTestSolver { std::function ModelPartFactory; @@ -159,7 +159,7 @@ KRATOS_TEST_CASE_IN_SUITE(TotalLagrangian3D8_SaintVenant_TransientSensitivity, K namespace // cpp internals { namespace test_solid_transient_sensitivity_cpp -{ // cotire unity guard +{ // unity build unity guard typedef TUblasSparseSpace SparseSpaceType; typedef TUblasDenseSpace LocalSpaceType; typedef LinearSolver LinearSolverType; diff --git a/applications/ConstitutiveModelsApplication/CMakeLists.txt b/applications/ConstitutiveModelsApplication/CMakeLists.txt index a057e0030de9..4a942739e5b5 100644 --- a/applications/ConstitutiveModelsApplication/CMakeLists.txt +++ b/applications/ConstitutiveModelsApplication/CMakeLists.txt @@ -83,6 +83,12 @@ pybind11_add_module(KratosConstitutiveModelsApplication MODULE THIN_LTO ${KRATOS target_link_libraries(KratosConstitutiveModelsApplication PRIVATE KratosConstitutiveModelsCore) set_target_properties(KratosConstitutiveModelsApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosConstitutiveModelsCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosConstitutiveModelsApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosConstitutiveModelsApplication PROPERTIES SUFFIX .pyd) @@ -93,12 +99,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosConstitutiveModelsApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosConstitutiveModelsCore) - cotire(KratosConstitutiveModelsApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/ConstitutiveModelsApplication.py KratosMultiphysics/ConstitutiveModelsApplication/__init__.py ) diff --git a/applications/ContactMechanicsApplication/CMakeLists.txt b/applications/ContactMechanicsApplication/CMakeLists.txt index 03f0ecc5c84f..8bcd3a7a0cf7 100644 --- a/applications/ContactMechanicsApplication/CMakeLists.txt +++ b/applications/ContactMechanicsApplication/CMakeLists.txt @@ -112,6 +112,12 @@ pybind11_add_module(KratosContactMechanicsApplication MODULE THIN_LTO ${KRATOS_C target_link_libraries(KratosContactMechanicsApplication PRIVATE KratosContactMechanicsCore) set_target_properties(KratosContactMechanicsApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosContactMechanicsCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosContactMechanicsApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosContactMechanicsApplication PROPERTIES SUFFIX .pyd) @@ -122,12 +128,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosContactMechanicsApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosContactMechanicsCore) - cotire(KratosContactMechanicsApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/ContactMechanicsApplication.py KratosMultiphysics/ContactMechanicsApplication/__init__.py ) diff --git a/applications/ContactStructuralMechanicsApplication/CMakeLists.txt b/applications/ContactStructuralMechanicsApplication/CMakeLists.txt index 637bbc64b77d..32c5b01758ed 100755 --- a/applications/ContactStructuralMechanicsApplication/CMakeLists.txt +++ b/applications/ContactStructuralMechanicsApplication/CMakeLists.txt @@ -46,6 +46,12 @@ pybind11_add_module(KratosContactStructuralMechanicsApplication MODULE THIN_LTO target_link_libraries(KratosContactStructuralMechanicsApplication PRIVATE KratosContactStructuralMechanicsCore) set_target_properties(KratosContactStructuralMechanicsApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosContactStructuralMechanicsCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosContactStructuralMechanicsApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES) # message("TestApplication subdir inc_dirs = ${inc_dirs}") @@ -59,17 +65,15 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosContactStructuralMechanicsApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - ## The interface_preprocess is not compatible with cotire (solve problem with explicit instantations) - set_source_files_properties (${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/interface_preprocess.cpp PROPERTIES COTIRE_EXCLUDED TRUE) +# Unity +if(CMAKE_UNITY_BUILD MATCHES ON) + ## The interface_preprocess is not compatible with unity build (solve problem with explicit instantations) + set_source_files_properties (${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/interface_preprocess.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE) file(GLOB condition_files ${CMAKE_CURRENT_SOURCE_DIR}/custom_conditions/*.cpp) foreach(condition_file ${condition_files}) - set_source_files_properties (${condition_file} PROPERTIES COTIRE_EXCLUDED TRUE) + set_source_files_properties (${condition_file} PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE) endforeach(condition_file) - cotire(KratosContactStructuralMechanicsCore) - cotire(KratosContactStructuralMechanicsApplication) -endif(USE_COTIRE MATCHES ON) +endif(CMAKE_UNITY_BUILD MATCHES ON) # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/ContactStructuralMechanicsApplication.py KratosMultiphysics/ContactStructuralMechanicsApplication/__init__.py ) diff --git a/applications/ContactStructuralMechanicsApplication/custom_conditions/penalty_frictional_mortar_contact_condition.cpp b/applications/ContactStructuralMechanicsApplication/custom_conditions/penalty_frictional_mortar_contact_condition.cpp index 3fb6e512cfd1..e6b80d130136 100644 --- a/applications/ContactStructuralMechanicsApplication/custom_conditions/penalty_frictional_mortar_contact_condition.cpp +++ b/applications/ContactStructuralMechanicsApplication/custom_conditions/penalty_frictional_mortar_contact_condition.cpp @@ -17,6 +17,7 @@ /* Mortar includes */ #include "custom_utilities/mortar_explicit_contribution_utilities.h" #include "custom_conditions/penalty_frictional_mortar_contact_condition.h" +#include "utilities/atomic_utilities.h" namespace Kratos { @@ -174,8 +175,7 @@ void PenaltyMethodFrictionalMortarContactCondition& r_force_residual = r_master_node.FastGetSolutionStepValue(FORCE_RESIDUAL); for (IndexType j = 0; j < TDim; ++j) { - #pragma omp atomic - r_force_residual[j] += rRHSVector[index + j]; + AtomicAdd(r_force_residual[j], rRHSVector[index + j]); } } for ( IndexType i_slave = 0; i_slave < TNumNodes; ++i_slave ) { @@ -185,8 +185,7 @@ void PenaltyMethodFrictionalMortarContactCondition& r_force_residual = r_slave_node.FastGetSolutionStepValue(FORCE_RESIDUAL); for (IndexType j = 0; j < TDim; ++j) { - #pragma omp atomic - r_force_residual[j] += rRHSVector[index + j]; + AtomicAdd(r_force_residual[j], rRHSVector[index + j]); } } } diff --git a/applications/ContactStructuralMechanicsApplication/custom_conditions/penalty_frictionless_mortar_contact_condition.cpp b/applications/ContactStructuralMechanicsApplication/custom_conditions/penalty_frictionless_mortar_contact_condition.cpp index a8d560b7ef21..c403de427078 100644 --- a/applications/ContactStructuralMechanicsApplication/custom_conditions/penalty_frictionless_mortar_contact_condition.cpp +++ b/applications/ContactStructuralMechanicsApplication/custom_conditions/penalty_frictionless_mortar_contact_condition.cpp @@ -17,6 +17,7 @@ /* Mortar includes */ #include "custom_utilities/mortar_explicit_contribution_utilities.h" #include "custom_conditions/penalty_frictionless_mortar_contact_condition.h" +#include "utilities/atomic_utilities.h" namespace Kratos { @@ -123,8 +124,7 @@ void PenaltyMethodFrictionlessMortarContactCondition& r_force_residual = r_master_node.FastGetSolutionStepValue(FORCE_RESIDUAL); for (IndexType j = 0; j < TDim; ++j) { - #pragma omp atomic - r_force_residual[j] += rRHSVector[index + j]; + AtomicAdd(r_force_residual[j], rRHSVector[index + j]); } } for ( IndexType i_slave = 0; i_slave < TNumNodes; ++i_slave ) { @@ -134,8 +134,7 @@ void PenaltyMethodFrictionlessMortarContactCondition& r_force_residual = r_slave_node.FastGetSolutionStepValue(FORCE_RESIDUAL); for (IndexType j = 0; j < TDim; ++j) { - #pragma omp atomic - r_force_residual[j] += rRHSVector[index + j]; + AtomicAdd(r_force_residual[j], rRHSVector[index + j]); } } } diff --git a/applications/ContactStructuralMechanicsApplication/custom_processes/alm_fast_init_process.cpp b/applications/ContactStructuralMechanicsApplication/custom_processes/alm_fast_init_process.cpp index 40fb8a2e65b6..61f3f691e5f0 100644 --- a/applications/ContactStructuralMechanicsApplication/custom_processes/alm_fast_init_process.cpp +++ b/applications/ContactStructuralMechanicsApplication/custom_processes/alm_fast_init_process.cpp @@ -16,6 +16,7 @@ // Project includes #include "contact_structural_mechanics_application_variables.h" #include "custom_processes/alm_fast_init_process.h" +#include "utilities/atomic_utilities.h" namespace Kratos { @@ -104,16 +105,14 @@ void ALMFastInit::Execute() for (auto& r_node : r_geom) { double& r_nodal_area = r_node.GetValue(NODAL_AREA); - #pragma omp atomic - r_nodal_area += 1.0; + AtomicAdd(r_nodal_area, 1.0); } if (p_prop->Has(FRICTION_COEFFICIENT)) { const double friction_coefficient = p_prop->GetValue(FRICTION_COEFFICIENT); for (auto& r_node : r_geom) { double& r_friction_coefficient = r_node.GetValue(FRICTION_COEFFICIENT); - #pragma omp atomic - r_friction_coefficient += friction_coefficient; + AtomicAdd(r_friction_coefficient, friction_coefficient); } } else { KRATOS_WARNING("ALMFastInit") << "WARNING:: Friction coefficient not defined, zero will be considered" << std::endl; diff --git a/applications/ContactStructuralMechanicsApplication/custom_strategies/custom_strategies/line_search_contact_strategy.h b/applications/ContactStructuralMechanicsApplication/custom_strategies/custom_strategies/line_search_contact_strategy.h index 900acdb7d7aa..bdf0446cd62c 100644 --- a/applications/ContactStructuralMechanicsApplication/custom_strategies/custom_strategies/line_search_contact_strategy.h +++ b/applications/ContactStructuralMechanicsApplication/custom_strategies/custom_strategies/line_search_contact_strategy.h @@ -25,6 +25,7 @@ #include "solving_strategies/strategies/line_search_strategy.h" #include "utilities/openmp_utils.h" #include "utilities/variable_utils.h" +#include "utilities/atomic_utilities.h" // Convergence criterias #include "solving_strategies/convergencecriterias/convergence_criteria.h" @@ -350,24 +351,17 @@ class LineSearchContactStrategy : const int num_nodes = static_cast(nodes_array.size()); #pragma omp parallel for - for(int i = 0; i < num_nodes; ++i) - { + for(int i = 0; i < num_nodes; ++i) { auto it_node = nodes_array.begin() + i; - for(auto itDoF = it_node->GetDofs().begin() ; itDoF != it_node->GetDofs().end() ; itDoF++) - { + for(auto itDoF = it_node->GetDofs().begin() ; itDoF != it_node->GetDofs().end() ; itDoF++) { const int j = (**itDoF).EquationId(); const std::size_t CurrVar = (**itDoF).GetVariable().Key(); - if ((CurrVar == DISPLACEMENT_X) || (CurrVar == DISPLACEMENT_Y) || (CurrVar == DISPLACEMENT_Z)) - { - #pragma omp atomic - normDisp += b[j] * b[j]; - } - else // Corresponding with contact - { - #pragma omp atomic - normLM += b[j] * b[j]; + if ((CurrVar == DISPLACEMENT_X) || (CurrVar == DISPLACEMENT_Y) || (CurrVar == DISPLACEMENT_Z)) { + AtomicAdd(normDisp, b[j] * b[j]); + } else { // Corresponding with contact + AtomicAdd(normLM, b[j] * b[j]); } } } diff --git a/applications/ContactStructuralMechanicsApplication/custom_strategies/custom_strategies/residualbased_newton_raphson_mpc_contact_strategy.h b/applications/ContactStructuralMechanicsApplication/custom_strategies/custom_strategies/residualbased_newton_raphson_mpc_contact_strategy.h index 8c6055b0b425..cd3a34a24c34 100755 --- a/applications/ContactStructuralMechanicsApplication/custom_strategies/custom_strategies/residualbased_newton_raphson_mpc_contact_strategy.h +++ b/applications/ContactStructuralMechanicsApplication/custom_strategies/custom_strategies/residualbased_newton_raphson_mpc_contact_strategy.h @@ -33,6 +33,7 @@ #include "utilities/variable_utils.h" #include "utilities/color_utilities.h" #include "utilities/math_utils.h" +#include "utilities/atomic_utilities.h" // // Processes // #include "processes/fast_transfer_between_model_parts_process.h" @@ -760,11 +761,9 @@ class ResidualBasedNewtonRaphsonMPCContactStrategy : for (IndexType i_node = 0; i_node < r_geometry.size(); ++i_node) { auto& r_node = r_geometry[i_node]; if (!enforce_ntn) { - #pragma omp atomic - r_node.GetValue(NODAL_PAUX) += 1.0; + AtomicAdd(r_node.GetValue(NODAL_PAUX), 1.0); } - #pragma omp atomic - r_node.GetValue(NODAL_MAUX) += lumping_factor[i_node] * domain_size; + AtomicAdd(r_node.GetValue(NODAL_MAUX), lumping_factor[i_node] * domain_size); } } } diff --git a/applications/ContactStructuralMechanicsApplication/custom_utilities/active_set_utilities.cpp b/applications/ContactStructuralMechanicsApplication/custom_utilities/active_set_utilities.cpp index d4c7c1002df6..b0ef76b948d1 100644 --- a/applications/ContactStructuralMechanicsApplication/custom_utilities/active_set_utilities.cpp +++ b/applications/ContactStructuralMechanicsApplication/custom_utilities/active_set_utilities.cpp @@ -17,6 +17,7 @@ #include "custom_utilities/active_set_utilities.h" #include "utilities/openmp_utils.h" #include "contact_structural_mechanics_application_variables.h" +#include "utilities/atomic_utilities.h" namespace Kratos { @@ -81,6 +82,7 @@ array_1d ComputePenaltyFrictionalActiveSet( is_converged[0] = 0; is_converged[1] = 0; + const std::size_t aux_1_index = 1; std::size_t& is_converged_0 = is_converged[0]; std::size_t& is_converged_1 = is_converged[1]; @@ -131,8 +133,7 @@ array_1d ComputePenaltyFrictionalActiveSet( // We activate the deactivated nodes and add the contribution if (it_node->IsNot(ACTIVE)) { it_node->Set(ACTIVE, true); - #pragma omp atomic - is_converged_0 += 1; + AtomicAdd(is_converged_0, aux_1_index); } // // BEGIN Adding debugging value of TANGENTIAL_CONTACT_STRESS @@ -146,8 +147,7 @@ array_1d ComputePenaltyFrictionalActiveSet( KRATOS_WARNING_IF("ComputePenaltyFrictionalActiveSet", PureSlip && EchoLevel > 0) << "This node is supposed to be on STICK state. Currently working on pure slip. Node ID: " << it_node->Id() << "\tTangent pressure: " << augmented_tangent_pressure << "\tNormal x friction coeff.: " << mu * std::abs(augmented_normal_pressure) << std::endl; if (is_slip && !PureSlip) { it_node->Set(SLIP, false); - #pragma omp atomic - is_converged_1 += 1; + AtomicAdd(is_converged_1, aux_1_index); } } else { // SLIP CASE const double norm_slip = norm_2(r_gt); @@ -155,8 +155,7 @@ array_1d ComputePenaltyFrictionalActiveSet( it_node->SetValue(AUGMENTED_TANGENT_CONTACT_PRESSURE, mu * augmented_normal_pressure * tangent_direction); if (!is_slip && !PureSlip) { it_node->Set(SLIP, true); - #pragma omp atomic - is_converged_1 += 1; + AtomicAdd(is_converged_1, aux_1_index); } else if (PureSlip) { it_node->Set(SLIP, true); } @@ -166,8 +165,7 @@ array_1d ComputePenaltyFrictionalActiveSet( if (it_node->Is(ACTIVE)) { it_node->Set(ACTIVE, false); it_node->Reset(SLIP); - #pragma omp atomic - is_converged_0 += 1; + AtomicAdd(is_converged_0, aux_1_index); } } } @@ -293,6 +291,7 @@ array_1d ComputeALMFrictionalActiveSet( is_converged[0] = 0; is_converged[1] = 0; + const std::size_t aux_1_index = 1; std::size_t& is_converged_0 = is_converged[0]; std::size_t& is_converged_1 = is_converged[1]; @@ -346,8 +345,7 @@ array_1d ComputeALMFrictionalActiveSet( if (it_node->IsNot(ACTIVE)) { noalias(it_node->FastGetSolutionStepValue(VECTOR_LAGRANGE_MULTIPLIER)) = r_nodal_normal * augmented_normal_pressure/scale_factor + (mu < std::numeric_limits::epsilon() ? zero_array : augmented_tangent_pressure_components/scale_factor); it_node->Set(ACTIVE, true); - #pragma omp atomic - is_converged_0 += 1; + AtomicAdd(is_converged_0, aux_1_index); } // Check for the slip/stick state @@ -360,8 +358,7 @@ array_1d ComputeALMFrictionalActiveSet( KRATOS_WARNING_IF("ComputeALMFrictionalActiveSet", PureSlip && EchoLevel > 0) << "This node is supposed to be on STICK state. Currently working on pure slip. Node ID: " << it_node->Id() << "\tTangent pressure: " << augmented_tangent_pressure << "\tNormal x friction coeff.: " << mu * std::abs(augmented_normal_pressure) << std::endl; if (is_slip && !PureSlip) { it_node->Set(SLIP, false); - #pragma omp atomic - is_converged_1 += 1; + AtomicAdd(is_converged_1, aux_1_index); } } else { // SLIP CASE const array_1d tangent_direction = tangent_lagrange_multiplier/norm_2(tangent_lagrange_multiplier); @@ -371,8 +368,7 @@ array_1d ComputeALMFrictionalActiveSet( if (!is_slip && !PureSlip) { it_node->Set(SLIP, true); - #pragma omp atomic - is_converged_1 += 1; + AtomicAdd(is_converged_1, aux_1_index); } else if (PureSlip) { it_node->Set(SLIP, true); } @@ -382,8 +378,7 @@ array_1d ComputeALMFrictionalActiveSet( if (it_node->Is(ACTIVE)) { it_node->Set(ACTIVE, false); it_node->Reset(SLIP); - #pragma omp atomic - is_converged_0 += 1; + AtomicAdd(is_converged_0, aux_1_index); } } } diff --git a/applications/ContactStructuralMechanicsApplication/custom_utilities/mortar_explicit_contribution_utilities.cpp b/applications/ContactStructuralMechanicsApplication/custom_utilities/mortar_explicit_contribution_utilities.cpp index 78ea79f4a9da..1382aa1f0cc8 100644 --- a/applications/ContactStructuralMechanicsApplication/custom_utilities/mortar_explicit_contribution_utilities.cpp +++ b/applications/ContactStructuralMechanicsApplication/custom_utilities/mortar_explicit_contribution_utilities.cpp @@ -15,6 +15,7 @@ // Project includes #include "custom_utilities/mortar_explicit_contribution_utilities.h" +#include "utilities/atomic_utilities.h" namespace Kratos { @@ -125,8 +126,7 @@ typename MortarExplicitContributionUtilities& r_slip_time_derivative_node = row(slip_time_derivative, i_node); @@ -330,8 +327,7 @@ typename MortarExplicitContributionUtilities& r_weighted_slip = r_slave_geometry[i_node].FastGetSolutionStepValue(WEIGHTED_SLIP); for (IndexType i_dim = 0; i_dim < TDim; ++i_dim) { - #pragma omp atomic - r_weighted_slip[i_dim] += slip_node[i_dim]; + AtomicAdd(r_weighted_slip[i_dim], slip_node[i_dim]); } } @@ -473,8 +469,7 @@ bool MortarExplicitContributionUtilities& DOperator = rPreviousMortarOperators.DOperator; for (IndexType i_node = 0; i_node < TNumNodes; ++i_node) { double& r_nodal_area = r_slave_geometry[i_node].GetValue(rAreaVariable); - #pragma omp atomic - r_nodal_area += DOperator(i_node, i_node); + AtomicAdd(r_nodal_area, DOperator(i_node, i_node)); } } diff --git a/applications/ContactStructuralMechanicsApplication/symbolic_generation/penalty_frictional_mortar_condition/penalty_frictional_mortar_contact_condition_template.cpp b/applications/ContactStructuralMechanicsApplication/symbolic_generation/penalty_frictional_mortar_condition/penalty_frictional_mortar_contact_condition_template.cpp index b7de58d8b3c8..f603db1e0a8b 100644 --- a/applications/ContactStructuralMechanicsApplication/symbolic_generation/penalty_frictional_mortar_condition/penalty_frictional_mortar_contact_condition_template.cpp +++ b/applications/ContactStructuralMechanicsApplication/symbolic_generation/penalty_frictional_mortar_condition/penalty_frictional_mortar_contact_condition_template.cpp @@ -17,6 +17,7 @@ /* Mortar includes */ #include "custom_utilities/mortar_explicit_contribution_utilities.h" #include "custom_conditions/penalty_frictional_mortar_contact_condition.h" +#include "utilities/atomic_utilities.h" namespace Kratos { @@ -174,8 +175,7 @@ void PenaltyMethodFrictionalMortarContactCondition& r_force_residual = r_master_node.FastGetSolutionStepValue(FORCE_RESIDUAL); for (IndexType j = 0; j < TDim; ++j) { - #pragma omp atomic - r_force_residual[j] += rRHSVector[index + j]; + AtomicAdd(r_force_residual[j], rRHSVector[index + j]); } } for ( IndexType i_slave = 0; i_slave < TNumNodes; ++i_slave ) { @@ -185,8 +185,7 @@ void PenaltyMethodFrictionalMortarContactCondition& r_force_residual = r_slave_node.FastGetSolutionStepValue(FORCE_RESIDUAL); for (IndexType j = 0; j < TDim; ++j) { - #pragma omp atomic - r_force_residual[j] += rRHSVector[index + j]; + AtomicAdd(r_force_residual[j], rRHSVector[index + j]); } } } diff --git a/applications/ContactStructuralMechanicsApplication/symbolic_generation/penalty_frictionless_mortar_condition/penalty_frictionless_mortar_contact_condition_template.cpp b/applications/ContactStructuralMechanicsApplication/symbolic_generation/penalty_frictionless_mortar_condition/penalty_frictionless_mortar_contact_condition_template.cpp index e152e6c8169c..5b5c936b5b11 100644 --- a/applications/ContactStructuralMechanicsApplication/symbolic_generation/penalty_frictionless_mortar_condition/penalty_frictionless_mortar_contact_condition_template.cpp +++ b/applications/ContactStructuralMechanicsApplication/symbolic_generation/penalty_frictionless_mortar_condition/penalty_frictionless_mortar_contact_condition_template.cpp @@ -17,6 +17,7 @@ /* Mortar includes */ #include "custom_utilities/mortar_explicit_contribution_utilities.h" #include "custom_conditions/penalty_frictionless_mortar_contact_condition.h" +#include "utilities/atomic_utilities.h" namespace Kratos { @@ -123,8 +124,7 @@ void PenaltyMethodFrictionlessMortarContactCondition& r_force_residual = r_master_node.FastGetSolutionStepValue(FORCE_RESIDUAL); for (IndexType j = 0; j < TDim; ++j) { - #pragma omp atomic - r_force_residual[j] += rRHSVector[index + j]; + AtomicAdd(r_force_residual[j], rRHSVector[index + j]); } } for ( IndexType i_slave = 0; i_slave < TNumNodes; ++i_slave ) { @@ -134,8 +134,7 @@ void PenaltyMethodFrictionlessMortarContactCondition& r_force_residual = r_slave_node.FastGetSolutionStepValue(FORCE_RESIDUAL); for (IndexType j = 0; j < TDim; ++j) { - #pragma omp atomic - r_force_residual[j] += rRHSVector[index + j]; + AtomicAdd(r_force_residual[j], rRHSVector[index + j]); } } } diff --git a/applications/ConvectionDiffusionApplication/CMakeLists.txt b/applications/ConvectionDiffusionApplication/CMakeLists.txt index 2152fdc856c2..e6f629192503 100644 --- a/applications/ConvectionDiffusionApplication/CMakeLists.txt +++ b/applications/ConvectionDiffusionApplication/CMakeLists.txt @@ -49,6 +49,12 @@ pybind11_add_module( KratosConvectionDiffusionApplication MODULE THIN_LTO ${KRAT target_link_libraries( KratosConvectionDiffusionApplication PRIVATE KratosConvectionDiffusionCore) set_target_properties( KratosConvectionDiffusionApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosConvectionDiffusionCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosConvectionDiffusionApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosConvectionDiffusionApplication PROPERTIES SUFFIX .pyd) @@ -59,12 +65,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosConvectionDiffusionApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosConvectionDiffusionCore) - cotire(KratosConvectionDiffusionApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/ConvectionDiffusionApplication.py KratosMultiphysics/ConvectionDiffusionApplication/__init__.py ) diff --git a/applications/DEMApplication/CMakeLists.txt b/applications/DEMApplication/CMakeLists.txt index a35018944244..b1cf11d5d352 100755 --- a/applications/DEMApplication/CMakeLists.txt +++ b/applications/DEMApplication/CMakeLists.txt @@ -109,6 +109,12 @@ set(KRATOS_DEM_APPLICATION_PYTHON_INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/AuxiliaryUtilities.cpp ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/analytic_tools/analytic_face_watcher.cpp ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/analytic_tools/analytic_particle_watcher.cpp + + # processes + ${CMAKE_CURRENT_SOURCE_DIR}/custom_processes/apply_kinematic_constraints_process.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_processes/apply_kinematic_constraints_to_walls_process.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_processes/apply_forces_and_moments_process.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_processes/apply_forces_and_moments_to_walls_process.cpp ) add_library(KratosDEMCore SHARED ${KRATOS_DEM_APPLICATION_CORE}) @@ -121,6 +127,11 @@ pybind11_add_module(KratosDEMApplication MODULE THIN_LTO ${KRATOS_DEM_APPLICATIO target_link_libraries(KratosDEMApplication PUBLIC KratosDEMCore) set_target_properties(KratosDEMApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosDEMCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosDEMApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) if(${ACTIVATE_DEBUG_MACRO} MATCHES ON) #MSI: Flag defined for debug Macro add_definitions(-DDEBUG_MACRO) @@ -136,12 +147,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosDEMApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosDEMCore) - cotire(KratosDEMApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/DEMApplication.py KratosMultiphysics/DEMApplication/__init__.py ) diff --git a/applications/DEMApplication/DEM_application.cpp b/applications/DEMApplication/DEM_application.cpp index 1dde76b58686..8d9f91f3f570 100644 --- a/applications/DEMApplication/DEM_application.cpp +++ b/applications/DEMApplication/DEM_application.cpp @@ -75,11 +75,10 @@ KRATOS_CREATE_VARIABLE(std::string, EXCENTRICITY_PROBABILITY_DISTRIBUTION) // OPTIONS AND FLAGS KRATOS_CREATE_VARIABLE(int, FORCE_INTEGRATION_GROUP) KRATOS_CREATE_VARIABLE(bool, IS_STICKY) -KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_VELOCITY) -KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_ANGULAR_VELOCITY) -KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_FORCE) -KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_MOMENT) -KRATOS_CREATE_VARIABLE(int, TABLE_NUMBER) // JIG: To erase (1 January 2019) +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_VELOCITY) // JIG: Backward compatibility, to erase +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_ANGULAR_VELOCITY) // JIG: Backward compatibility, to erase +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_FORCE) // JIG: Backward compatibility, to erase +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_MOMENT) // JIG: Backward compatibility, to erase KRATOS_CREATE_VARIABLE(int, TOP) KRATOS_CREATE_VARIABLE(int, BOTTOM) KRATOS_CREATE_VARIABLE(int, BOUNDING_BOX_OPTION) @@ -183,6 +182,7 @@ KRATOS_CREATE_VARIABLE(double, PARTICLE_DENSITY) KRATOS_CREATE_VARIABLE(double, FRICTION) //deprecated since April 6th, 2020 KRATOS_CREATE_VARIABLE(double, STATIC_FRICTION) KRATOS_CREATE_VARIABLE(double, DYNAMIC_FRICTION) +KRATOS_CREATE_VARIABLE(double, FRICTION_DECAY) KRATOS_CREATE_VARIABLE(double, COEFFICIENT_OF_RESTITUTION) KRATOS_CREATE_VARIABLE(double, PARTICLE_ROTATION_DAMP_RATIO) KRATOS_CREATE_VARIABLE(double, DAMPING_GAMMA) @@ -532,11 +532,10 @@ void KratosDEMApplication::Register() { KRATOS_REGISTER_VARIABLE(BOTTOM) KRATOS_REGISTER_VARIABLE(FORCE_INTEGRATION_GROUP) KRATOS_REGISTER_VARIABLE(IS_STICKY) - KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_VELOCITY) - KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_ANGULAR_VELOCITY) - KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_FORCE) - KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_MOMENT) - KRATOS_REGISTER_VARIABLE(TABLE_NUMBER) // JIG: To erase (1 January 2019) + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_VELOCITY) // JIG: Backward compatibility, to erase + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_ANGULAR_VELOCITY) // JIG: Backward compatibility, to erase + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_FORCE) // JIG: Backward compatibility, to erase + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS(TABLE_NUMBER_MOMENT) // JIG: Backward compatibility, to erase KRATOS_REGISTER_VARIABLE(SHEAR_STRAIN_PARALLEL_TO_BOND_OPTION) KRATOS_REGISTER_VARIABLE(POISSON_EFFECT_OPTION) KRATOS_REGISTER_VARIABLE(ROLLING_FRICTION_OPTION) @@ -635,6 +634,7 @@ void KratosDEMApplication::Register() { KRATOS_REGISTER_VARIABLE(FRICTION) //deprecated since April 6th, 2020 KRATOS_REGISTER_VARIABLE(STATIC_FRICTION) KRATOS_REGISTER_VARIABLE(DYNAMIC_FRICTION) + KRATOS_REGISTER_VARIABLE(FRICTION_DECAY) KRATOS_REGISTER_VARIABLE(COEFFICIENT_OF_RESTITUTION) KRATOS_REGISTER_VARIABLE(PARTICLE_ROTATION_DAMP_RATIO) KRATOS_REGISTER_VARIABLE(DAMPING_GAMMA) diff --git a/applications/DEMApplication/DEM_application_variables.h b/applications/DEMApplication/DEM_application_variables.h index 89eaf6814a2e..f0d65175d657 100644 --- a/applications/DEMApplication/DEM_application_variables.h +++ b/applications/DEMApplication/DEM_application_variables.h @@ -57,12 +57,11 @@ namespace Kratos KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, int, BOTTOM) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, int, FORCE_INTEGRATION_GROUP) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, bool, IS_STICKY) - KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, TABLE_NUMBER_VELOCITY) - KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, TABLE_NUMBER_ANGULAR_VELOCITY) - KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, TABLE_NUMBER_FORCE) - KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, TABLE_NUMBER_MOMENT) + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, TABLE_NUMBER_VELOCITY) // JIG: Backward compatibility, to erase + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, TABLE_NUMBER_ANGULAR_VELOCITY) // JIG: Backward compatibility, to erase + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, TABLE_NUMBER_FORCE) // JIG: Backward compatibility, to erase + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, TABLE_NUMBER_MOMENT) // JIG: Backward compatibility, to erase KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS(DEM_APPLICATION, CONTACT_IMPULSE) - KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, int, TABLE_NUMBER) // JIG: To erase (1 January 2019) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, int, BOUNDING_BOX_OPTION) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, int, ROTATION_OPTION) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, int, CRITICAL_TIME_OPTION) @@ -163,6 +162,7 @@ namespace Kratos KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, FRICTION) //deprecated since April 6th, 2020 KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, STATIC_FRICTION) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, DYNAMIC_FRICTION) + KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, FRICTION_DECAY) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, COEFFICIENT_OF_RESTITUTION) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, PARTICLE_ROTATION_DAMP_RATIO) KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, DAMPING_GAMMA) diff --git a/applications/DEMApplication/custom_conditions/RigidFace.cpp b/applications/DEMApplication/custom_conditions/RigidFace.cpp index cd695e1711ea..70124b35525f 100644 --- a/applications/DEMApplication/custom_conditions/RigidFace.cpp +++ b/applications/DEMApplication/custom_conditions/RigidFace.cpp @@ -401,22 +401,25 @@ bool RigidFace3D::CheckProjectionFallsInside(SphericParticle *p_particle) { const array_1d& P = p_particle->GetGeometry()[0].Coordinates(); const Geometry >& geom = GetGeometry(); - const array_1d w = P - geom[0].Coordinates(); - array_1d u1 = geom[1].Coordinates() - geom[0].Coordinates(); - array_1d u2 = geom[2].Coordinates() - geom[0].Coordinates(); - array_1d u2_copy; - noalias(u2_copy) = u2; - array_1d n; - GeometryFunctions::CrossProduct(u1, u2, n); - GeometryFunctions::CrossProduct(w, u2_copy, u2); - const double beta = DEM_INNER_PRODUCT_3(u2, n); - GeometryFunctions::CrossProduct(u1, w, u1); - const double gamma = DEM_INNER_PRODUCT_3(u1, n); - const double n2 = DEM_INNER_PRODUCT_3(n, n); - const double alpha = n2 - beta - gamma; - - const bool falls_inside = alpha >= 0 && beta >= 0 && gamma >= 0 && alpha <= n2 && beta <= n2 && gamma <= n2; - + const array_1d& P1 = geom[0].Coordinates(); + const array_1d& P2 = geom[1].Coordinates(); + const array_1d& P3 = geom[2].Coordinates(); + const array_1d w = P - P1; + array_1d side_1 = P2 - P1; + array_1d side_2 = P3 - P1; + array_1d normal; + array_1d side_1_cross_w; + array_1d w_cross_side_2; + GeometryFunctions::CrossProduct(side_1, side_2, normal); + GeometryFunctions::CrossProduct(side_1, w, side_1_cross_w); + GeometryFunctions::CrossProduct(w, side_2, w_cross_side_2); + const double normal2 = DEM_INNER_PRODUCT_3(normal, normal); + const double beta = DEM_INNER_PRODUCT_3(w_cross_side_2, normal) / normal2; + const double gamma = DEM_INNER_PRODUCT_3(side_1_cross_w, normal) / normal2; + const double alpha = 1 - beta - gamma; + const bool falls_inside = (alpha >= 0 && beta >= 0 && gamma >= 0 + && alpha <= 1 && beta <= 1 && gamma <= 1); + return falls_inside; } diff --git a/applications/DEMApplication/custom_conditions/analytic_RigidFace.cpp b/applications/DEMApplication/custom_conditions/analytic_RigidFace.cpp index f2dc51dadc5d..41fd79d11b56 100644 --- a/applications/DEMApplication/custom_conditions/analytic_RigidFace.cpp +++ b/applications/DEMApplication/custom_conditions/analytic_RigidFace.cpp @@ -48,8 +48,8 @@ int AnalyticRigidFace3D::CheckSide(SphericParticle* p_particle) mContactingNeighbourSignedIds.push_back(signed_id); if (just_changed_side){ const bool is_a_crosser = CheckProjectionFallsInside(p_particle); - - if (is_a_crosser || true){ + + if (is_a_crosser){ mNumberThroughput += side_sign; mCrossers.push_back(signed_id); mMasses.push_back(p_particle->GetMass()); diff --git a/applications/DEMApplication/custom_conditions/dem_wall.cpp b/applications/DEMApplication/custom_conditions/dem_wall.cpp index 361778953327..7af517aa51c5 100644 --- a/applications/DEMApplication/custom_conditions/dem_wall.cpp +++ b/applications/DEMApplication/custom_conditions/dem_wall.cpp @@ -257,6 +257,7 @@ double DEMWall::GetYoung() const { return GetProperties()[YOU double DEMWall::GetPoisson() const { return GetProperties()[POISSON_RATIO]; } double DEMWall::GetTgOfStaticFrictionAngle() const { return GetProperties()[STATIC_FRICTION]; } double DEMWall::GetTgOfDynamicFrictionAngle() const { return GetProperties()[DYNAMIC_FRICTION]; } +double DEMWall::GetFrictionDecayCoefficient() const { return GetProperties()[FRICTION_DECAY]; } void DEMWall::FinalizeSolutionStep(const ProcessInfo& r_process_info) diff --git a/applications/DEMApplication/custom_conditions/dem_wall.h b/applications/DEMApplication/custom_conditions/dem_wall.h index e143b8332de5..414433e450a6 100644 --- a/applications/DEMApplication/custom_conditions/dem_wall.h +++ b/applications/DEMApplication/custom_conditions/dem_wall.h @@ -92,6 +92,7 @@ class KRATOS_API(DEM_APPLICATION) DEMWall : public Condition double GetPoisson() const; double GetTgOfStaticFrictionAngle() const; double GetTgOfDynamicFrictionAngle() const; + double GetFrictionDecayCoefficient() const; std::vector mNeighbourSphericParticles; std::vector > mRightHandSideVector; diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Bentonite_Colloid_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_D_Bentonite_Colloid_CL.cpp index 3be69b184a64..07c603955c72 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Bentonite_Colloid_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Bentonite_Colloid_CL.cpp @@ -109,7 +109,7 @@ namespace Kratos { }*/ CalculateTangentialForceWithNeighbour(normal_contact_force, OldLocalContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, element1, element2, indentation, previous_indentation); + LocalRelVel, sliding, element1, element2, indentation, previous_indentation); } @@ -172,6 +172,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalRelVel[3], bool& sliding, SphericParticle* const element, NeighbourClassType* const neighbour, diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Bentonite_Colloid_CL.h b/applications/DEMApplication/custom_constitutive/DEM_D_Bentonite_Colloid_CL.h index 9c7391c8c005..008e5466b3a2 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Bentonite_Colloid_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Bentonite_Colloid_CL.h @@ -74,6 +74,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalRelVel[3], bool& sliding, SphericParticle* const element, NeighbourClassType* const neighbour, diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Conical_damage_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_D_Conical_damage_CL.cpp index d9dffb8e6e58..2809b0abb24f 100755 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Conical_damage_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Conical_damage_CL.cpp @@ -180,7 +180,7 @@ namespace Kratos { double MaximumAdmisibleShearForce; CalculateTangentialForce(normal_contact_force, OldLocalElasticContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, p_element1, p_element2, original_equiv_radius, equiv_young, elastic_indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); + LocalRelVel, sliding, p_element1, p_element2, original_equiv_radius, equiv_young, elastic_indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); double& elastic_energy = p_element1->GetElasticEnergy(); DEM_D_Hertz_viscous_Coulomb::CalculateElasticEnergyDEM(elastic_energy, elastic_indentation, LocalElasticContactForce); @@ -318,7 +318,7 @@ namespace Kratos { double MaximumAdmisibleShearForce; CalculateTangentialForceWithFEM(normal_contact_force, OldLocalElasticContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, p_element, wall, original_effective_radius, equiv_young, elastic_indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); + LocalRelVel, sliding, p_element, wall, original_effective_radius, equiv_young, elastic_indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); double& elastic_energy = p_element->GetElasticEnergy(); DEM_D_Hertz_viscous_Coulomb::CalculateElasticEnergyFEM(elastic_energy, elastic_indentation, LocalElasticContactForce); @@ -361,6 +361,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalRelVel[3], bool& sliding, ContactInfoSphericParticle* const element1, ContactInfoSphericParticle* const element2, @@ -390,6 +391,10 @@ namespace Kratos { const double neighbour_tg_of_dynamic_friction_angle = element2->GetTgOfDynamicFrictionAngle(); double equiv_tg_of_dynamic_fri_ang = 0.5 * (my_tg_of_dynamic_friction_angle + neighbour_tg_of_dynamic_friction_angle); + const double my_friction_decay_coefficient = element1->GetFrictionDecayCoefficient(); + const double neighbour_friction_decay_coefficient = element2->GetFrictionDecayCoefficient(); + double equiv_friction_decay_coefficient = 0.5 * (my_friction_decay_coefficient + neighbour_friction_decay_coefficient); + if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< element1->Id()< MaximumAdmisibleShearForce) MaximumAdmisibleShearForce = normal_contact_force * equiv_tg_of_dynamic_fri_ang; + const double ShearRelVel = sqrt(LocalRelVel[0] * LocalRelVel[0] + LocalRelVel[1] * LocalRelVel[1]); + double equiv_friction = equiv_tg_of_dynamic_fri_ang + (equiv_tg_of_static_fri_ang - equiv_tg_of_dynamic_fri_ang) * exp(-equiv_friction_decay_coefficient * ShearRelVel); + + MaximumAdmisibleShearForce = normal_contact_force * equiv_friction; const double tangential_contact_force_0 = LocalElasticContactForce[0] + ViscoDampingLocalContactForce[0]; const double tangential_contact_force_1 = LocalElasticContactForce[1] + ViscoDampingLocalContactForce[1]; @@ -485,6 +492,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalRelVel[3], bool& sliding, ContactInfoSphericParticle* const element, Condition* const wall, @@ -514,6 +522,10 @@ namespace Kratos { const double neighbour_tg_of_dynamic_friction_angle = wall->GetProperties()[DYNAMIC_FRICTION]; double equiv_tg_of_dynamic_fri_ang = 0.5 * (my_tg_of_dynamic_friction_angle + neighbour_tg_of_dynamic_friction_angle); + const double my_friction_decay_coefficient = element->GetFrictionDecayCoefficient(); + const double neighbour_friction_decay_coefficient = wall->GetProperties()[FRICTION_DECAY]; + double equiv_friction_decay_coefficient = 0.5 * (my_friction_decay_coefficient + neighbour_friction_decay_coefficient); + if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< element->Id()< MaximumAdmisibleShearForce) MaximumAdmisibleShearForce = normal_contact_force * equiv_tg_of_dynamic_fri_ang; + const double ShearRelVel = sqrt(LocalRelVel[0] * LocalRelVel[0] + LocalRelVel[1] * LocalRelVel[1]); + double equiv_friction = equiv_tg_of_dynamic_fri_ang + (equiv_tg_of_static_fri_ang - equiv_tg_of_dynamic_fri_ang) * exp(-equiv_friction_decay_coefficient * ShearRelVel); + + MaximumAdmisibleShearForce = normal_contact_force * equiv_friction; const double tangential_contact_force_0 = LocalElasticContactForce[0] + ViscoDampingLocalContactForce[0]; const double tangential_contact_force_1 = LocalElasticContactForce[1] + ViscoDampingLocalContactForce[1]; diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Conical_damage_CL.h b/applications/DEMApplication/custom_constitutive/DEM_D_Conical_damage_CL.h index df3317249ed9..c9932765745d 100755 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Conical_damage_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Conical_damage_CL.h @@ -97,6 +97,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalRelVel[3], bool& sliding, ContactInfoSphericParticle* const element1, ContactInfoSphericParticle* const element2, @@ -112,6 +113,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalReltVel[3], bool& sliding, ContactInfoSphericParticle* const element, Condition* const wall, diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Hertz_viscous_Coulomb_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_D_Hertz_viscous_Coulomb_CL.cpp index 77e6877526f6..5ab1209cacc1 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Hertz_viscous_Coulomb_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Hertz_viscous_Coulomb_CL.cpp @@ -96,7 +96,7 @@ namespace Kratos { double MaximumAdmisibleShearForce; CalculateTangentialForceWithNeighbour(normal_contact_force, OldLocalElasticContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, element1, element2, indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); + LocalRelVel, sliding, element1, element2, indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); double& elastic_energy = element1->GetElasticEnergy(); CalculateElasticEnergyDEM(elastic_energy, indentation, LocalElasticContactForce); @@ -191,7 +191,7 @@ namespace Kratos { double MaximumAdmisibleShearForce; CalculateTangentialForceWithNeighbour(normal_contact_force, OldLocalElasticContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, element, wall, indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); + LocalRelVel, sliding, element, wall, indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); double& elastic_energy = element->GetElasticEnergy(); CalculateElasticEnergyFEM(elastic_energy, indentation, LocalElasticContactForce);//MSIMSI @@ -212,6 +212,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalRelVel[3], bool& sliding, SphericParticle* const element, NeighbourClassType* const neighbour, @@ -239,12 +240,18 @@ namespace Kratos { const double neighbour_tg_of_dynamic_friction_angle = neighbour->GetProperties()[DYNAMIC_FRICTION]; const double equiv_tg_of_dynamic_fri_ang = 0.5 * (my_tg_of_dynamic_friction_angle + neighbour_tg_of_dynamic_friction_angle); + const double my_friction_decay_coefficient = element->GetFrictionDecayCoefficient(); + const double neighbour_friction_decay_coefficient = neighbour->GetProperties()[FRICTION_DECAY]; + double equiv_friction_decay_coefficient = 0.5 * (my_friction_decay_coefficient + neighbour_friction_decay_coefficient); + if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< element->Id()< MaximumAdmisibleShearForce) MaximumAdmisibleShearForce = normal_contact_force * equiv_tg_of_dynamic_fri_ang; + const double ShearRelVel = sqrt(LocalRelVel[0] * LocalRelVel[0] + LocalRelVel[1] * LocalRelVel[1]); + double equiv_friction = equiv_tg_of_dynamic_fri_ang + (equiv_tg_of_static_fri_ang - equiv_tg_of_dynamic_fri_ang) * exp(-equiv_friction_decay_coefficient * ShearRelVel); + + MaximumAdmisibleShearForce = normal_contact_force * equiv_friction; const double tangential_contact_force_0 = LocalElasticContactForce[0] + ViscoDampingLocalContactForce[0]; const double tangential_contact_force_1 = LocalElasticContactForce[1] + ViscoDampingLocalContactForce[1]; diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Hertz_viscous_Coulomb_CL.h b/applications/DEMApplication/custom_constitutive/DEM_D_Hertz_viscous_Coulomb_CL.h index 572d2e05bd7e..aaa2a0eeeb7b 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Hertz_viscous_Coulomb_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Hertz_viscous_Coulomb_CL.h @@ -77,6 +77,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalRelVel[3], bool& sliding, SphericParticle* const element, NeighbourClassType* const neighbour, diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Linear_viscous_Coulomb_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_D_Linear_viscous_Coulomb_CL.cpp index 9d09f78b2033..47cc852dfe35 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Linear_viscous_Coulomb_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Linear_viscous_Coulomb_CL.cpp @@ -91,7 +91,7 @@ namespace Kratos { double MaximumAdmisibleShearForce; CalculateTangentialForceWithNeighbour(normal_contact_force, OldLocalElasticContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, element1, element2, indentation, previous_indentation, ElasticShearForceModulus, MaximumAdmisibleShearForce); + LocalRelVel, sliding, element1, element2, indentation, previous_indentation, ElasticShearForceModulus, MaximumAdmisibleShearForce); double& elastic_energy = element1->GetElasticEnergy(); CalculateElasticEnergyDEM(elastic_energy, indentation, LocalElasticContactForce); @@ -203,7 +203,7 @@ namespace Kratos { double MaximumAdmisibleShearForce; CalculateTangentialForceWithNeighbour(normal_contact_force, OldLocalElasticContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, element, wall, indentation, previous_indentation, ElasticShearForceModulus, MaximumAdmisibleShearForce); + LocalRelVel, sliding, element, wall, indentation, previous_indentation, ElasticShearForceModulus, MaximumAdmisibleShearForce); double& elastic_energy = element->GetElasticEnergy(); CalculateElasticEnergyFEM(elastic_energy, indentation, LocalElasticContactForce);//MSIMSI @@ -233,12 +233,16 @@ namespace Kratos { } + double DEM_D_Linear_viscous_Coulomb::GetTgOfStaticFrictionAngleOfElement(SphericParticle* element){ + return element->GetTgOfStaticFrictionAngle(); + } + double DEM_D_Linear_viscous_Coulomb::GetTgOfDynamicFrictionAngleOfElement(SphericParticle* element){ return element->GetTgOfDynamicFrictionAngle(); } - double DEM_D_Linear_viscous_Coulomb::GetTgOfStaticFrictionAngleOfElement(SphericParticle* element){ - return element->GetTgOfStaticFrictionAngle(); + double DEM_D_Linear_viscous_Coulomb::GetFrictionDecayCoefficient(SphericParticle* element){ + return element->GetFrictionDecayCoefficient(); } std::size_t DEM_D_Linear_viscous_Coulomb::GetElementId(SphericParticle* element){ diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Linear_viscous_Coulomb_CL.h b/applications/DEMApplication/custom_constitutive/DEM_D_Linear_viscous_Coulomb_CL.h index fd5f3bae59e4..574901329dd1 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Linear_viscous_Coulomb_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Linear_viscous_Coulomb_CL.h @@ -78,6 +78,7 @@ namespace Kratos { double LocalElasticContactForce[3], double ViscoDampingLocalContactForce[3], const double LocalDeltDisp[3], + const double LocalRelVel[3], bool& sliding, SphericParticle* const element, NeighbourClassType* const neighbour, @@ -99,12 +100,18 @@ namespace Kratos { const double neighbour_tg_of_dynamic_friction_angle = neighbour->GetProperties()[DYNAMIC_FRICTION]; const double equiv_tg_of_dynamic_fri_ang = 0.5 * (my_tg_of_dynamic_friction_angle + neighbour_tg_of_dynamic_friction_angle); + const double my_friction_decay_coefficient = GetFrictionDecayCoefficient(element); + const double neighbour_friction_decay_coefficient = neighbour->GetProperties()[FRICTION_DECAY]; + double equiv_friction_decay_coefficient = 0.5 * (my_friction_decay_coefficient + neighbour_friction_decay_coefficient); + if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< GetElementId(element)< MaximumAdmisibleShearForce) MaximumAdmisibleShearForce = normal_contact_force * equiv_tg_of_dynamic_fri_ang; + const double ShearRelVel = sqrt(LocalRelVel[0] * LocalRelVel[0] + LocalRelVel[1] * LocalRelVel[1]); + double equiv_friction = equiv_tg_of_dynamic_fri_ang + (equiv_tg_of_static_fri_ang - equiv_tg_of_dynamic_fri_ang) * exp(-equiv_friction_decay_coefficient * ShearRelVel); + + MaximumAdmisibleShearForce = normal_contact_force * equiv_friction; const double tangential_contact_force_0 = LocalElasticContactForce[0] + ViscoDampingLocalContactForce[0]; const double tangential_contact_force_1 = LocalElasticContactForce[1] + ViscoDampingLocalContactForce[1]; @@ -188,8 +195,9 @@ namespace Kratos { double LocalDeltDisp[3]); protected: - double GetTgOfDynamicFrictionAngleOfElement(SphericParticle* element); double GetTgOfStaticFrictionAngleOfElement(SphericParticle* element); + double GetTgOfDynamicFrictionAngleOfElement(SphericParticle* element); + double GetFrictionDecayCoefficient(SphericParticle* element); std::size_t GetElementId(SphericParticle* element); private: diff --git a/applications/DEMApplication/custom_constitutive/DEM_D_Stress_dependent_cohesive_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_D_Stress_dependent_cohesive_CL.cpp index 7984c6710c4e..f653f06f09a7 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_D_Stress_dependent_cohesive_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_D_Stress_dependent_cohesive_CL.cpp @@ -130,7 +130,7 @@ namespace Kratos { double MaximumAdmisibleShearForce; CalculateTangentialForceWithNeighbour(normal_contact_force, OldLocalElasticContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, element1, element2, indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); + LocalRelVel, sliding, element1, element2, indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); double& elastic_energy = element1->GetElasticEnergy(); DEM_D_Linear_viscous_Coulomb::CalculateElasticEnergyDEM(elastic_energy, indentation, LocalElasticContactForce); @@ -273,7 +273,7 @@ namespace Kratos { double MaximumAdmisibleShearForce; CalculateTangentialForceWithNeighbour(normal_contact_force, OldLocalElasticContactForce, LocalElasticContactForce, ViscoDampingLocalContactForce, LocalDeltDisp, - sliding, element, wall, indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); + LocalRelVel, sliding, element, wall, indentation, previous_indentation, AuxElasticShearForce, MaximumAdmisibleShearForce); double& elastic_energy = element->GetElasticEnergy(); DEM_D_Linear_viscous_Coulomb::CalculateElasticEnergyFEM(elastic_energy, indentation, LocalElasticContactForce); diff --git a/applications/DEMApplication/custom_constitutive/DEM_Dempack_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_Dempack_CL.cpp index a674a60c6676..6c15d34e5b50 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_Dempack_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_Dempack_CL.cpp @@ -175,6 +175,7 @@ namespace Kratos { LocalElasticExtraContactForce, LocalCoordSystem, LocalDeltDisp, + LocalRelVel, kt_el, equiv_shear, contact_sigma, @@ -375,9 +376,10 @@ namespace Kratos { // /* void DEM_Dempack::CalculateTangentialForces(double OldLocalElasticContactForce[3], double LocalElasticContactForce[3], - double LocalElasticExtraContactForce[3], + double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, diff --git a/applications/DEMApplication/custom_constitutive/DEM_Dempack_CL.h b/applications/DEMApplication/custom_constitutive/DEM_Dempack_CL.h index 7ca04c21a882..dd4781f11c43 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_Dempack_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_Dempack_CL.h @@ -111,6 +111,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, diff --git a/applications/DEMApplication/custom_constitutive/DEM_Dempack_dev_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_Dempack_dev_CL.cpp index fab30b8d5978..c9143fd06d68 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_Dempack_dev_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_Dempack_dev_CL.cpp @@ -253,6 +253,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, @@ -302,13 +303,16 @@ namespace Kratos { else { double equiv_tg_of_static_fri_ang = 0.5 * (element1->GetTgOfStaticFrictionAngle() + element2->GetTgOfStaticFrictionAngle()); double equiv_tg_of_dynamic_fri_ang = 0.5 * (element1->GetTgOfDynamicFrictionAngle() + element2->GetTgOfDynamicFrictionAngle()); + double equiv_friction_decay_coefficient = 0.5 * (element1->GetFrictionDecayCoefficient() + element2->GetFrictionDecayCoefficient()); if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< element1->Id()< Frictional_ShearForceMax) Frictional_ShearForceMax = equiv_tg_of_dynamic_fri_ang * LocalElasticContactForce[2]; + const double ShearRelVel = sqrt(LocalRelVel[0] * LocalRelVel[0] + LocalRelVel[1] * LocalRelVel[1]); + double equiv_friction = equiv_tg_of_dynamic_fri_ang + (equiv_tg_of_static_fri_ang - equiv_tg_of_dynamic_fri_ang) * exp(-equiv_friction_decay_coefficient * ShearRelVel); + + double Frictional_ShearForceMax = equiv_friction * LocalElasticContactForce[2]; if (Frictional_ShearForceMax < 0.0) { Frictional_ShearForceMax = 0.0; diff --git a/applications/DEMApplication/custom_constitutive/DEM_Dempack_dev_CL.h b/applications/DEMApplication/custom_constitutive/DEM_Dempack_dev_CL.h index a9fe9a364f40..b41a0405cc69 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_Dempack_dev_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_Dempack_dev_CL.h @@ -50,6 +50,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, diff --git a/applications/DEMApplication/custom_constitutive/DEM_KDEM_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_KDEM_CL.cpp index 0b9d1860a047..949e415137f5 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_KDEM_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_KDEM_CL.cpp @@ -190,6 +190,7 @@ namespace Kratos { LocalElasticExtraContactForce, LocalCoordSystem, LocalDeltDisp, + LocalRelVel, kt_el, equiv_shear, contact_sigma, @@ -272,6 +273,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, @@ -320,13 +322,16 @@ namespace Kratos { else { double equiv_tg_of_static_fri_ang = 0.5 * (element1->GetTgOfStaticFrictionAngle() + element2->GetTgOfStaticFrictionAngle()); double equiv_tg_of_dynamic_fri_ang = 0.5 * (element1->GetTgOfDynamicFrictionAngle() + element2->GetTgOfDynamicFrictionAngle()); + double equiv_friction_decay_coefficient = 0.5 * (element1->GetFrictionDecayCoefficient() + element2->GetFrictionDecayCoefficient()); if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< element1->Id()< Frictional_ShearForceMax) Frictional_ShearForceMax = equiv_tg_of_dynamic_fri_ang * LocalElasticContactForce[2]; + const double ShearRelVel = sqrt(LocalRelVel[0] * LocalRelVel[0] + LocalRelVel[1] * LocalRelVel[1]); + double equiv_friction = equiv_tg_of_dynamic_fri_ang + (equiv_tg_of_static_fri_ang - equiv_tg_of_dynamic_fri_ang) * exp(-equiv_friction_decay_coefficient * ShearRelVel); + + double Frictional_ShearForceMax = equiv_friction * LocalElasticContactForce[2]; if (Frictional_ShearForceMax < 0.0) { diff --git a/applications/DEMApplication/custom_constitutive/DEM_KDEM_CL.h b/applications/DEMApplication/custom_constitutive/DEM_KDEM_CL.h index acca9a97c803..a6d3174dcea0 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_KDEM_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_KDEM_CL.h @@ -87,6 +87,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, diff --git a/applications/DEMApplication/custom_constitutive/DEM_KDEM_Rankine_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_KDEM_Rankine_CL.cpp index bc604cd48b5e..3ae39b4691a4 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_KDEM_Rankine_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_KDEM_Rankine_CL.cpp @@ -94,6 +94,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, @@ -125,13 +126,16 @@ namespace Kratos { double ShearForceNow = sqrt(LocalElasticContactForce[0] * LocalElasticContactForce[0] + LocalElasticContactForce[1] * LocalElasticContactForce[1]); double equiv_tg_of_static_fri_ang = 0.5 * (element1->GetTgOfStaticFrictionAngle() + element2->GetTgOfStaticFrictionAngle()); double equiv_tg_of_dynamic_fri_ang = 0.5 * (element1->GetTgOfDynamicFrictionAngle() + element2->GetTgOfDynamicFrictionAngle()); + double equiv_friction_decay_coefficient = 0.5 * (element1->GetFrictionDecayCoefficient() + element2->GetFrictionDecayCoefficient()); if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< element1->Id()< Frictional_ShearForceMax) Frictional_ShearForceMax = equiv_tg_of_dynamic_fri_ang * LocalElasticContactForce[2]; + const double ShearRelVel = sqrt(LocalRelVel[0] * LocalRelVel[0] + LocalRelVel[1] * LocalRelVel[1]); + double equiv_friction = equiv_tg_of_dynamic_fri_ang + (equiv_tg_of_static_fri_ang - equiv_tg_of_dynamic_fri_ang) * exp(-equiv_friction_decay_coefficient * ShearRelVel); + + double Frictional_ShearForceMax = equiv_friction * LocalElasticContactForce[2]; if (Frictional_ShearForceMax < 0.0) { Frictional_ShearForceMax = 0.0; diff --git a/applications/DEMApplication/custom_constitutive/DEM_KDEM_Rankine_CL.h b/applications/DEMApplication/custom_constitutive/DEM_KDEM_Rankine_CL.h index 1d1920e48547..ad710fbb6a8a 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_KDEM_Rankine_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_KDEM_Rankine_CL.h @@ -44,6 +44,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, diff --git a/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_CL.cpp index 557f0de65140..3b37ac5fa0ab 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_CL.cpp @@ -75,6 +75,7 @@ namespace Kratos { LocalElasticExtraContactForce, LocalCoordSystem, LocalDeltDisp, + LocalRelVel, kt_el, equiv_shear, contact_sigma, @@ -207,6 +208,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, @@ -336,13 +338,16 @@ namespace Kratos { } else { double equiv_tg_of_static_fri_ang = 0.5 * (element1->GetTgOfStaticFrictionAngle() + element2->GetTgOfStaticFrictionAngle()); double equiv_tg_of_dynamic_fri_ang = 0.5 * (element1->GetTgOfDynamicFrictionAngle() + element2->GetTgOfDynamicFrictionAngle()); + double equiv_friction_decay_coefficient = 0.5 * (element1->GetFrictionDecayCoefficient() + element2->GetFrictionDecayCoefficient()); if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< element1->Id()< maximum_frictional_shear_force) maximum_frictional_shear_force = equiv_tg_of_dynamic_fri_ang * LocalElasticContactForce[2]; + const double ShearRelVel = sqrt(LocalRelVel[0] * LocalRelVel[0] + LocalRelVel[1] * LocalRelVel[1]); + double equiv_friction = equiv_tg_of_dynamic_fri_ang + (equiv_tg_of_static_fri_ang - equiv_tg_of_dynamic_fri_ang) * exp(-equiv_friction_decay_coefficient * ShearRelVel); + + double maximum_frictional_shear_force = equiv_friction * LocalElasticContactForce[2]; if (maximum_frictional_shear_force < 0.0) maximum_frictional_shear_force = 0.0; diff --git a/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_CL.h b/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_CL.h index a54a8f6da95e..13ffe35a5215 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_CL.h @@ -65,6 +65,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, diff --git a/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_parallel_bond_CL.cpp b/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_parallel_bond_CL.cpp index 75a50b370a88..1435f37b3c93 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_parallel_bond_CL.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_parallel_bond_CL.cpp @@ -130,6 +130,7 @@ namespace Kratos { LocalElasticExtraContactForce, LocalCoordSystem, LocalDeltDisp, + LocalRelVel, kt_el, equiv_shear, contact_sigma, @@ -311,6 +312,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, @@ -445,17 +447,24 @@ namespace Kratos { const double neighbour_tg_of_dynamic_friction_angle = element2->GetTgOfDynamicFrictionAngle(); const double equiv_tg_of_dynamic_fri_ang = 0.5 * (my_tg_of_dynamic_friction_angle + neighbour_tg_of_dynamic_friction_angle); + const double my_friction_decay_coefficient = element1->GetFrictionDecayCoefficient(); + const double neighbour_friction_decay_coefficient = element2->GetProperties()[FRICTION_DECAY]; + double equiv_friction_decay_coefficient = 0.5 * (my_friction_decay_coefficient + neighbour_friction_decay_coefficient); + if(equiv_tg_of_static_fri_ang < 0.0 || equiv_tg_of_dynamic_fri_ang < 0.0) { KRATOS_ERROR << "The averaged friction is negative for one contact of element with Id: "<< element1->Id()< max_admissible_shear_force) { max_admissible_shear_force = mUnbondedLocalElasticContactForce2 * equiv_tg_of_static_fri_ang; diff --git a/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_parallel_bond_CL.h b/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_parallel_bond_CL.h index ed1c58ce9284..b91141960c70 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_parallel_bond_CL.h +++ b/applications/DEMApplication/custom_constitutive/DEM_KDEM_with_damage_parallel_bond_CL.h @@ -82,6 +82,7 @@ namespace Kratos { double LocalElasticExtraContactForce[3], double LocalCoordSystem[3][3], double LocalDeltDisp[3], + double LocalRelVel[3], const double kt_el, const double equiv_shear, double& contact_sigma, diff --git a/applications/DEMApplication/custom_constitutive/DEM_beam_constitutive_law.cpp b/applications/DEMApplication/custom_constitutive/DEM_beam_constitutive_law.cpp index c8e351ba904b..ca3661f82378 100644 --- a/applications/DEMApplication/custom_constitutive/DEM_beam_constitutive_law.cpp +++ b/applications/DEMApplication/custom_constitutive/DEM_beam_constitutive_law.cpp @@ -38,6 +38,12 @@ namespace Kratos { pProp->GetValue(DYNAMIC_FRICTION) = pProp->GetValue(FRICTION); } } + if(!pProp->Has(FRICTION_DECAY)) { + KRATOS_WARNING("DEM")<GetValue(FRICTION_DECAY) = 500.0; + } if(!pProp->Has(YOUNG_MODULUS)) { KRATOS_WARNING("DEM")<GetValue(DYNAMIC_FRICTION) = pProp->GetValue(FRICTION); } } + if(!pProp->Has(FRICTION_DECAY)) { + KRATOS_WARNING("DEM")<GetValue(FRICTION_DECAY) = 500.0; + } if(!pProp->Has(YOUNG_MODULUS)) { KRATOS_WARNING("DEM")<GetValue(DYNAMIC_FRICTION) = pProp->GetValue(FRICTION); } } + if(!pProp->Has(FRICTION_DECAY)) { + KRATOS_WARNING("DEM")<GetValue(FRICTION_DECAY) = 500.0; + } if(!pProp->Has(YOUNG_MODULUS)) { KRATOS_WARNING("DEM")< angular_velocity = central_node.FastGetSolutionStepValue(ANGULAR_VELOCITY); array_1d angular_momentum; double LocalTensor[3][3]; diff --git a/applications/DEMApplication/custom_elements/spheric_particle.cpp b/applications/DEMApplication/custom_elements/spheric_particle.cpp index 9ccb7829a623..112c11845ea8 100644 --- a/applications/DEMApplication/custom_elements/spheric_particle.cpp +++ b/applications/DEMApplication/custom_elements/spheric_particle.cpp @@ -2086,6 +2086,7 @@ double SphericParticle::GetRollingFrictionWithWalls() double SphericParticle::GetPoisson() { return GetFastProperties()->GetPoisson(); } double SphericParticle::GetTgOfStaticFrictionAngle() { return GetFastProperties()->GetTgOfStaticFrictionAngle(); } double SphericParticle::GetTgOfDynamicFrictionAngle() { return GetFastProperties()->GetTgOfDynamicFrictionAngle(); } +double SphericParticle::GetFrictionDecayCoefficient() { return GetFastProperties()->GetFrictionDecayCoefficient(); } double SphericParticle::GetCoefficientOfRestitution() { return GetFastProperties()->GetCoefficientOfRestitution(); } double SphericParticle::GetLnOfRestitCoeff() { return GetFastProperties()->GetLnOfRestitCoeff(); } double SphericParticle::GetDensity() { return GetFastProperties()->GetDensity(); } @@ -2105,6 +2106,7 @@ void SphericParticle::SetRollingFrictionWithWallsFromProperties(double* rollin void SphericParticle::SetPoissonFromProperties(double* poisson) { GetFastProperties()->SetPoissonFromProperties( poisson); } void SphericParticle::SetTgOfStaticFrictionAngleFromProperties(double* tg_of_static_friction_angle) { GetFastProperties()->SetTgOfStaticFrictionAngleFromProperties( tg_of_static_friction_angle); } void SphericParticle::SetTgOfDynamicFrictionAngleFromProperties(double* tg_of_dynamic_friction_angle){ GetFastProperties()->SetTgOfDynamicFrictionAngleFromProperties( tg_of_dynamic_friction_angle);} +void SphericParticle::SetFrictionDecayCoefficientFromProperties(double* friction_decay_coefficient) { GetFastProperties()->SetFrictionDecayCoefficientFromProperties( friction_decay_coefficient);} void SphericParticle::SetCoefficientOfRestitutionFromProperties(double* coefficient_of_restitution) { GetFastProperties()->SetCoefficientOfRestitutionFromProperties( coefficient_of_restitution); } void SphericParticle::SetLnOfRestitCoeffFromProperties(double* ln_of_restit_coeff) { GetFastProperties()->SetLnOfRestitCoeffFromProperties( ln_of_restit_coeff); } void SphericParticle::SetDensityFromProperties(double* density) { GetFastProperties()->SetDensityFromProperties( density); } @@ -2133,6 +2135,7 @@ double SphericParticle::SlowGetRollingFrictionWithWalls() const { return GetProp double SphericParticle::SlowGetPoisson() const { return GetProperties()[POISSON_RATIO]; } double SphericParticle::SlowGetTgOfStaticFrictionAngle() const { return GetProperties()[STATIC_FRICTION]; } double SphericParticle::SlowGetTgOfDynamicFrictionAngle() const { return GetProperties()[DYNAMIC_FRICTION]; } +double SphericParticle::SlowGetFrictionDecayCoefficient() const { return GetProperties()[FRICTION_DECAY]; } double SphericParticle::SlowGetCoefficientOfRestitution() const { return GetProperties()[COEFFICIENT_OF_RESTITUTION]; } double SphericParticle::SlowGetDensity() const { return GetProperties()[PARTICLE_DENSITY]; } int SphericParticle::SlowGetParticleMaterial() const { return GetProperties()[PARTICLE_MATERIAL]; } diff --git a/applications/DEMApplication/custom_elements/spheric_particle.h b/applications/DEMApplication/custom_elements/spheric_particle.h index 6d3589a6f8f2..36fe44a9efdc 100644 --- a/applications/DEMApplication/custom_elements/spheric_particle.h +++ b/applications/DEMApplication/custom_elements/spheric_particle.h @@ -205,6 +205,8 @@ virtual double GetTgOfStaticFrictionAngle(); void SetTgOfStaticFrictionAngleFromProperties(double* tg_of_static_friction_angle); virtual double GetTgOfDynamicFrictionAngle(); void SetTgOfDynamicFrictionAngleFromProperties(double* tg_of_dynamic_friction_angle); +virtual double GetFrictionDecayCoefficient(); +void SetFrictionDecayCoefficientFromProperties(double* tg_of_dynamic_friction_angle); virtual double GetCoefficientOfRestitution(); void SetCoefficientOfRestitutionFromProperties(double* coefficient_of_restitution); virtual double GetLnOfRestitCoeff(); @@ -236,6 +238,7 @@ double SlowGetRollingFrictionWithWalls() const; double SlowGetPoisson() const; double SlowGetTgOfStaticFrictionAngle() const; double SlowGetTgOfDynamicFrictionAngle() const; +double SlowGetFrictionDecayCoefficient() const; double SlowGetCoefficientOfRestitution() const; double SlowGetDensity() const; double SlowGetParticleCohesion() const; diff --git a/applications/DEMApplication/custom_processes/apply_forces_and_moments_process.cpp b/applications/DEMApplication/custom_processes/apply_forces_and_moments_process.cpp new file mode 100644 index 000000000000..9e0e04c22a20 --- /dev/null +++ b/applications/DEMApplication/custom_processes/apply_forces_and_moments_process.cpp @@ -0,0 +1,203 @@ +#include "apply_forces_and_moments_process.hpp" +#include "utilities/parallel_utilities.h" + +namespace Kratos +{ + /* Public functions *******************************************************/ + ApplyForcesAndMomentsProcess::ApplyForcesAndMomentsProcess( + ModelPart& rModelPart, + Parameters rParameters + ) : mrModelPart(rModelPart), mParameters(rParameters), mInterval(rParameters) + { + KRATOS_TRY + + //only include validation with c++11 since raw_literals do not exist in c++03 + Parameters default_parameters( R"( + { + "help" : "This process applies loads over the particles in a certain submodelpart, for a certain time interval", + "mesh_id" : 0, + "model_part_name" : "please_specify_model_part_name", + "force_settings" : { + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "moment_settings" : { + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "interval" : [0.0, 1e30] + } )" ); + + + // Some values need to be mandatorily prescribed since no meaningful default value exist. For this reason try accessing to them + // So that an error is thrown if they don't exist + rParameters["model_part_name"]; + + // Now validate agains defaults -- this also ensures no type mismatch + rParameters.ValidateAndAssignDefaults(default_parameters); + + mForceFunctions.clear(); + mMomentFunctions.clear(); + + mpForceTable.clear(); + mpMomentTable.clear(); + + for(int i=0; i<3; i++) { + if(rParameters["force_settings"]["value"][i].IsNull()) { + mForceValueIsNumeric[i] = true; + mForceValues[i] = 0.0; + mForceFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + if(rParameters["force_settings"]["value"][i].IsNumber()) { + mForceValueIsNumeric[i] = true; + mForceValues[i] = rParameters["force_settings"]["value"][i].GetDouble(); + mForceFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + mForceValueIsNumeric[i] = false; + mForceFunctions.push_back(PythonGenericFunctionUtility(rParameters["force_settings"]["value"][i].GetString())); + } + } + + if(rParameters["force_settings"]["table"][i].IsNull()) { + mForceTableId[i] = 0; + } + else { + mForceTableId[i] = rParameters["force_settings"]["table"][i].GetInt(); + } + mpForceTable.push_back(mrModelPart.pGetTable(mForceTableId[i])); // because I can't construct an array_1d of these + + if(rParameters["moment_settings"]["value"][i].IsNull()) { + mMomentValueIsNumeric[i] = true; + mMomentValues[i] = 0.0; + mMomentFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + if(rParameters["moment_settings"]["value"][i].IsNumber()) { + mMomentValueIsNumeric[i] = true; + mMomentValues[i] = rParameters["moment_settings"]["value"][i].GetDouble(); + mMomentFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + mMomentValueIsNumeric[i] = false; + mMomentFunctions.push_back(PythonGenericFunctionUtility(rParameters["moment_settings"]["value"][i].GetString())); + } + } + + if(rParameters["moment_settings"]["table"][i].IsNull()) { + mMomentTableId[i] = 0; + } + else { + mMomentTableId[i] = rParameters["moment_settings"]["table"][i].GetInt(); + } + mpMomentTable.push_back(mrModelPart.pGetTable(mMomentTableId[i])); // because I can't construct an array_1d of these + } + + mParameters = rParameters; + + KRATOS_CATCH(""); + } + + ApplyForcesAndMomentsProcess::~ApplyForcesAndMomentsProcess() + { + + } + + void ApplyForcesAndMomentsProcess::Execute() + { + } + + void ApplyForcesAndMomentsProcess::ExecuteInitializeSolutionStep() + { + KRATOS_TRY; + + + const double time = mrModelPart.GetProcessInfo()[TIME]; + + if(!mInterval.IsInInterval(time)) return; + + block_for_each(mrModelPart.Nodes(), [&](Node<3>& rNode) + { + + array_1d& force = rNode.FastGetSolutionStepValue(EXTERNAL_APPLIED_FORCE); + array_1d& moment = rNode.FastGetSolutionStepValue(EXTERNAL_APPLIED_MOMENT); + + for(int i=0; i<3; i++) { + if (mForceTableId[i] != 0) { + force[i] = mpForceTable[i]->GetValue(time); + } + else { + double force_value = 0.0; + if(mForceValueIsNumeric[i]) { + force_value = mForceValues[i]; + } + else { + force_value = mForceFunctions[i].CallFunction(rNode.X(), rNode.Y(), rNode.Z(), time); + } + force[i] = force_value; + } + + if (mMomentTableId[i] != 0) { + moment[i] = mpMomentTable[i]->GetValue(time); + } + else { + double moment_value = 0.0; + if(mMomentValueIsNumeric[i]) { + moment_value = mMomentValues[i]; + } + else { + moment_value = mMomentFunctions[i].CallFunction(rNode.X(), rNode.Y(), rNode.Z(), time); + } + moment[i] = moment_value; + } + } + }); + + KRATOS_CATCH(""); + } + + void ApplyForcesAndMomentsProcess::ExecuteFinalizeSolutionStep() + { + KRATOS_TRY; + + + const double time = mrModelPart.GetProcessInfo()[TIME]; + + if(mInterval.IsInInterval(time)) return; + + block_for_each(mrModelPart.Nodes(), [&](Node<3>& rNode) + { + rNode.FastGetSolutionStepValue(EXTERNAL_APPLIED_FORCE) = ZeroVector(3); + rNode.FastGetSolutionStepValue(EXTERNAL_APPLIED_MOMENT) = ZeroVector(3); + }); + + KRATOS_CATCH(""); + } + + std::string ApplyForcesAndMomentsProcess::Info() const + { + return "ApplyForcesAndMomentsProcess"; + } + + void ApplyForcesAndMomentsProcess::PrintInfo(std::ostream& rOStream) const + { + rOStream << "ApplyForcesAndMomentsProcess"; + } + + void ApplyForcesAndMomentsProcess::PrintData(std::ostream& rOStream) const + { + } + + /* External functions *****************************************************/ + + /// output stream function + inline std::ostream& operator << ( + std::ostream& rOStream, + const ApplyForcesAndMomentsProcess& rThis) + { + rThis.PrintData(rOStream); + return rOStream; + } + +} diff --git a/applications/DEMApplication/custom_processes/apply_forces_and_moments_process.hpp b/applications/DEMApplication/custom_processes/apply_forces_and_moments_process.hpp new file mode 100644 index 000000000000..fdf955194a3c --- /dev/null +++ b/applications/DEMApplication/custom_processes/apply_forces_and_moments_process.hpp @@ -0,0 +1,247 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main author: Joaquín Irazábal González +// + +#if !defined(KRATOS_APPLY_FORCES_AND_MOMENTS_PROCESS ) +#define KRATOS_APPLY_FORCES_AND_MOMENTS_PROCESS + + + +// System includes +#include +#include + + +// External includes + + +// Project includes +#include "includes/table.h" +#include "includes/kratos_parameters.h" +#include "processes/process.h" +#include "utilities/interval_utility.h" +#include "utilities/python_function_callback_utility.h" +#include "DEM_application_variables.h" + +namespace Kratos +{ + ///@addtogroup DEMApplication + ///@{ + + ///@name Kratos Globals + ///@{ + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Enum's + ///@{ + + ///@} + ///@name Functions + ///@{ + + ///@} + ///@name Kratos Classes + ///@{ + + /// Auxiliary process to apply forces and moments to particles. + /** This process sets the EXTERNAL_APPLIED_FORCE and EXTERNAL_APPLIED_MOMENT variables + over particles. + */ + class ApplyForcesAndMomentsProcess: public Process + { + public: + ///@name Type Definitions + ///@{ + + /// Pointer definition of ApplyForcesAndMomentsProcess + KRATOS_CLASS_POINTER_DEFINITION(ApplyForcesAndMomentsProcess); + + /// Defining a table with double argument and result type as table type. + typedef Table TableType; + + ///@} + ///@name Life Cycle + ///@{ + + /// Constructor + ApplyForcesAndMomentsProcess(ModelPart& rModelPart, Parameters rParameters); + + /// Destructor. + ~ApplyForcesAndMomentsProcess() override; + + + ///@} + ///@name Operators + ///@{ + + + ///@} + ///@name Operations + ///@{ + + void Execute() override; + + void ExecuteInitializeSolutionStep() override; + + void ExecuteFinalizeSolutionStep() override; + + ///@} + ///@name Access + ///@{ + + + ///@} + ///@name Inquiry + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + /// Turn back information as a string. + std::string Info() const override; + + /// Print information about this object. + void PrintInfo(std::ostream& rOStream) const override; + + /// Print object's data. + void PrintData(std::ostream& rOStream) const override; + + + ///@} + ///@name Friends + ///@{ + + + ///@} + + protected: + ///@name Protected static Member Variables + ///@{ + + + ///@} + ///@name Protected member Variables + ///@{ + + + ///@} + ///@name Protected Operators + ///@{ + + + ///@} + ///@name Protected Operations + ///@{ + + ///@} + ///@name Protected Access + ///@{ + + + ///@} + ///@name Protected Inquiry + ///@{ + + + ///@} + ///@name Protected LifeCycle + ///@{ + + + ///@} + + private: + ///@name Static Member Variables + ///@{ + + + ///@} + ///@name Member Variables + ///@{ + + ModelPart& mrModelPart; + Parameters mParameters; + IntervalUtility mInterval; + array_1d mForceValueIsNumeric; + array_1d mMomentValueIsNumeric; + array_1d mForceValues; + array_1d mMomentValues; + std::vector mForceFunctions; + std::vector mMomentFunctions; + array_1d mForceTableId; + array_1d mMomentTableId; + std::vector mpForceTable; + std::vector mpMomentTable; + + ///@} + ///@name Private Operators + ///@{ + + + ///@} + ///@name Private Operations + ///@{ + + + ///@} + ///@name Private Access + ///@{ + + + ///@} + ///@name Private Inquiry + ///@{ + + + ///@} + ///@name Un accessible methods + ///@{ + + /// Assignment operator. + ApplyForcesAndMomentsProcess& operator=(ApplyForcesAndMomentsProcess const& rOther); + + /// Copy constructor. + ApplyForcesAndMomentsProcess(ApplyForcesAndMomentsProcess const& rOther); + + + ///@} + + }; // Class ApplyForcesAndMomentsProcess + + ///@} + + ///@name Type Definitions + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + + /// output stream function + inline std::ostream& operator << ( + std::ostream& rOStream, + const ApplyForcesAndMomentsProcess& rThis); + + ///@} + + ///@} addtogroup block + +} // namespace Kratos. + +#endif // KRATOS_APPLY_FORCES_AND_MOMENTS_PROCESS defined diff --git a/applications/DEMApplication/custom_processes/apply_forces_and_moments_to_walls_process.cpp b/applications/DEMApplication/custom_processes/apply_forces_and_moments_to_walls_process.cpp new file mode 100644 index 000000000000..2dace5769109 --- /dev/null +++ b/applications/DEMApplication/custom_processes/apply_forces_and_moments_to_walls_process.cpp @@ -0,0 +1,204 @@ +#include "apply_forces_and_moments_to_walls_process.hpp" +#include "utilities/parallel_utilities.h" + +namespace Kratos +{ + /* Public functions *******************************************************/ + ApplyForcesAndMomentsToWallsProcess::ApplyForcesAndMomentsToWallsProcess( + ModelPart& rModelPart, + Parameters rParameters + ) : mrModelPart(rModelPart), mParameters(rParameters), mInterval(rParameters) + { + KRATOS_TRY + + //only include validation with c++11 since raw_literals do not exist in c++03 + Parameters default_parameters( R"( + { + "help" : "This process applies loads over the rigid walls in a certain submodelpart, for a certain time interval", + "mesh_id" : 0, + "model_part_name" : "please_specify_model_part_name", + "force_settings" : { + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "moment_settings" : { + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "interval" : [0.0, 1e30] + } )" ); + + + + // Some values need to be mandatorily prescribed since no meaningful default value exist. For this reason try accessing to them + // So that an error is thrown if they don't exist + rParameters["model_part_name"]; + + // Now validate agains defaults -- this also ensures no type mismatch + rParameters.ValidateAndAssignDefaults(default_parameters); + + mForceFunctions.clear(); + mMomentFunctions.clear(); + + mpForceTable.clear(); + mpMomentTable.clear(); + + for(int i=0; i<3; i++) { + if(rParameters["force_settings"]["value"][i].IsNull()) { + mForceValueIsNumeric[i] = true; + mForceValues[i] = 0.0; + mForceFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + if(rParameters["force_settings"]["value"][i].IsNumber()) { + mForceValueIsNumeric[i] = true; + mForceValues[i] = rParameters["force_settings"]["value"][i].GetDouble(); + mForceFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + mForceValueIsNumeric[i] = false; + mForceFunctions.push_back(PythonGenericFunctionUtility(rParameters["force_settings"]["value"][i].GetString())); + } + } + + if(rParameters["force_settings"]["table"][i].IsNull()) { + mForceTableId[i] = 0; + } + else { + mForceTableId[i] = rParameters["force_settings"]["table"][i].GetInt(); + } + mpForceTable.push_back(mrModelPart.pGetTable(mForceTableId[i])); // because I can't construct an array_1d of these + + if(rParameters["moment_settings"]["value"][i].IsNull()) { + mMomentValueIsNumeric[i] = true; + mMomentValues[i] = 0.0; + mMomentFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + if(rParameters["moment_settings"]["value"][i].IsNumber()) { + mMomentValueIsNumeric[i] = true; + mMomentValues[i] = rParameters["moment_settings"]["value"][i].GetDouble(); + mMomentFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + mMomentValueIsNumeric[i] = false; + mMomentFunctions.push_back(PythonGenericFunctionUtility(rParameters["moment_settings"]["value"][i].GetString())); + } + } + + if(rParameters["moment_settings"]["table"][i].IsNull()) { + mMomentTableId[i] = 0; + } + else { + mMomentTableId[i] = rParameters["moment_settings"]["table"][i].GetInt(); + } + mpMomentTable.push_back(mrModelPart.pGetTable(mMomentTableId[i])); // because I can't construct an array_1d of these + } + + mParameters = rParameters; + + KRATOS_CATCH(""); + } + + ApplyForcesAndMomentsToWallsProcess::~ApplyForcesAndMomentsToWallsProcess() + { + + } + + void ApplyForcesAndMomentsToWallsProcess::Execute() + { + } + + void ApplyForcesAndMomentsToWallsProcess::ExecuteInitializeSolutionStep() + { + KRATOS_TRY; + + + const double time = mrModelPart.GetProcessInfo()[TIME]; + + if(!mInterval.IsInInterval(time)) return; + + block_for_each(mrModelPart.Elements(), [&](Element& rElement) + { + + array_1d& force = rElement.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_FORCE); + array_1d& moment = rElement.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_MOMENT); + + for(int i=0; i<3; i++) { + if (mForceTableId[i] != 0) { + force[i] = mpForceTable[i]->GetValue(time); + } + else { + double force_value = 0.0; + if(mForceValueIsNumeric[i]) { + force_value = mForceValues[i]; + } + else { + force_value = mForceFunctions[i].CallFunction(rElement.GetGeometry()[0].X(), rElement.GetGeometry()[0].Y(), rElement.GetGeometry()[0].Z(), time); + } + force[i] = force_value; + } + + if (mMomentTableId[i] != 0) { + moment[i] = mpMomentTable[i]->GetValue(time); + } + else { + double moment_value = 0.0; + if(mMomentValueIsNumeric[i]) { + moment_value = mMomentValues[i]; + } + else { + moment_value = mMomentFunctions[i].CallFunction(rElement.GetGeometry()[0].X(), rElement.GetGeometry()[0].Y(), rElement.GetGeometry()[0].Z(), time); + } + moment[i] = moment_value; + } + } + }); + + KRATOS_CATCH(""); + } + + void ApplyForcesAndMomentsToWallsProcess::ExecuteFinalizeSolutionStep() + { + KRATOS_TRY; + + + const double time = mrModelPart.GetProcessInfo()[TIME]; + + if(mInterval.IsInInterval(time)) return; + + block_for_each(mrModelPart.Elements(), [&](Element& rElement) + { + rElement.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_FORCE) = ZeroVector(3); + rElement.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_MOMENT) = ZeroVector(3); + }); + + KRATOS_CATCH(""); + } + + std::string ApplyForcesAndMomentsToWallsProcess::Info() const + { + return "ApplyForcesAndMomentsToWallsProcess"; + } + + void ApplyForcesAndMomentsToWallsProcess::PrintInfo(std::ostream& rOStream) const + { + rOStream << "ApplyForcesAndMomentsToWallsProcess"; + } + + void ApplyForcesAndMomentsToWallsProcess::PrintData(std::ostream& rOStream) const + { + } + + /* External functions *****************************************************/ + + /// output stream function + inline std::ostream& operator << ( + std::ostream& rOStream, + const ApplyForcesAndMomentsToWallsProcess& rThis) + { + rThis.PrintData(rOStream); + return rOStream; + } + +} diff --git a/applications/DEMApplication/custom_processes/apply_forces_and_moments_to_walls_process.hpp b/applications/DEMApplication/custom_processes/apply_forces_and_moments_to_walls_process.hpp new file mode 100644 index 000000000000..0e2803a3d125 --- /dev/null +++ b/applications/DEMApplication/custom_processes/apply_forces_and_moments_to_walls_process.hpp @@ -0,0 +1,247 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main author: Joaquín Irazábal González +// + +#if !defined(KRATOS_APPLY_FORCES_AND_MOMENTS_TO_WALLS_PROCESS ) +#define KRATOS_APPLY_FORCES_AND_MOMENTS_TO_WALLS_PROCESS + + + +// System includes +#include +#include + + +// External includes + + +// Project includes +#include "includes/table.h" +#include "includes/kratos_parameters.h" +#include "processes/process.h" +#include "utilities/interval_utility.h" +#include "utilities/python_function_callback_utility.h" +#include "DEM_application_variables.h" + +namespace Kratos +{ + ///@addtogroup DEMApplication + ///@{ + + ///@name Kratos Globals + ///@{ + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Enum's + ///@{ + + ///@} + ///@name Functions + ///@{ + + ///@} + ///@name Kratos Classes + ///@{ + + /// Auxiliary process to apply forces and moments to walls. + /** This process sets the EXTERNAL_APPLIED_FORCE and EXTERNAL_APPLIED_MOMENT variables + over walls. + */ + class ApplyForcesAndMomentsToWallsProcess: public Process + { + public: + ///@name Type Definitions + ///@{ + + /// Pointer definition of ApplyForcesAndMomentsToWallsProcess + KRATOS_CLASS_POINTER_DEFINITION(ApplyForcesAndMomentsToWallsProcess); + + /// Defining a table with double argument and result type as table type. + typedef Table TableType; + + ///@} + ///@name Life Cycle + ///@{ + + /// Constructor + ApplyForcesAndMomentsToWallsProcess(ModelPart& rModelPart, Parameters rParameters); + + /// Destructor. + ~ApplyForcesAndMomentsToWallsProcess() override; + + + ///@} + ///@name Operators + ///@{ + + + ///@} + ///@name Operations + ///@{ + + void Execute() override; + + void ExecuteInitializeSolutionStep() override; + + void ExecuteFinalizeSolutionStep() override; + + ///@} + ///@name Access + ///@{ + + + ///@} + ///@name Inquiry + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + /// Turn back information as a string. + std::string Info() const override; + + /// Print information about this object. + void PrintInfo(std::ostream& rOStream) const override; + + /// Print object's data. + void PrintData(std::ostream& rOStream) const override; + + + ///@} + ///@name Friends + ///@{ + + + ///@} + + protected: + ///@name Protected static Member Variables + ///@{ + + + ///@} + ///@name Protected member Variables + ///@{ + + + ///@} + ///@name Protected Operators + ///@{ + + + ///@} + ///@name Protected Operations + ///@{ + + ///@} + ///@name Protected Access + ///@{ + + + ///@} + ///@name Protected Inquiry + ///@{ + + + ///@} + ///@name Protected LifeCycle + ///@{ + + + ///@} + + private: + ///@name Static Member Variables + ///@{ + + + ///@} + ///@name Member Variables + ///@{ + + ModelPart& mrModelPart; + Parameters mParameters; + IntervalUtility mInterval; + array_1d mForceValueIsNumeric; + array_1d mMomentValueIsNumeric; + array_1d mForceValues; + array_1d mMomentValues; + std::vector mForceFunctions; + std::vector mMomentFunctions; + array_1d mForceTableId; + array_1d mMomentTableId; + std::vector mpForceTable; + std::vector mpMomentTable; + + ///@} + ///@name Private Operators + ///@{ + + + ///@} + ///@name Private Operations + ///@{ + + + ///@} + ///@name Private Access + ///@{ + + + ///@} + ///@name Private Inquiry + ///@{ + + + ///@} + ///@name Un accessible methods + ///@{ + + /// Assignment operator. + ApplyForcesAndMomentsToWallsProcess& operator=(ApplyForcesAndMomentsToWallsProcess const& rOther); + + /// Copy constructor. + ApplyForcesAndMomentsToWallsProcess(ApplyForcesAndMomentsToWallsProcess const& rOther); + + + ///@} + + }; // Class ApplyForcesAndMomentsToWallsProcess + + ///@} + + ///@name Type Definitions + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + + /// output stream function + inline std::ostream& operator << ( + std::ostream& rOStream, + const ApplyForcesAndMomentsToWallsProcess& rThis); + + ///@} + + ///@} addtogroup block + +} // namespace Kratos. + +#endif // KRATOS_APPLY_FORCES_AND_MOMENTS_TO_WALLS_PROCESS defined diff --git a/applications/DEMApplication/custom_processes/apply_kinematic_constraints_process.cpp b/applications/DEMApplication/custom_processes/apply_kinematic_constraints_process.cpp new file mode 100644 index 000000000000..022f1ffcedbb --- /dev/null +++ b/applications/DEMApplication/custom_processes/apply_kinematic_constraints_process.cpp @@ -0,0 +1,246 @@ +#include "apply_kinematic_constraints_process.hpp" +#include "utilities/parallel_utilities.h" + +namespace Kratos +{ + /* Public functions *******************************************************/ + ApplyKinematicConstraintsProcess::ApplyKinematicConstraintsProcess( + ModelPart& rModelPart, + Parameters rParameters + ) : Process(Flags()) , mrModelPart(rModelPart), mParameters(rParameters), mInterval(rParameters) + { + KRATOS_TRY + + //only include validation with c++11 since raw_literals do not exist in c++03 + Parameters default_parameters( R"( + { + "help" : "This process applies constraints to the particles in a certain submodelpart, for a certain time interval", + "mesh_id" : 0, + "model_part_name" : "please_specify_model_part_name", + "velocity_constraints_settings" : { + "constrained" : [true,true,true], + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "angular_velocity_constraints_settings" : { + "constrained" : [true,true,true], + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "interval" : [0.0, 1e30] + } )" ); + + + + // Some values need to be mandatorily prescribed since no meaningful default value exist. For this reason try accessing to them + // So that an error is thrown if they don't exist + rParameters["model_part_name"]; + + // Now validate agains defaults -- this also ensures no type mismatch + rParameters.ValidateAndAssignDefaults(default_parameters); + + mVelocityFunctions.clear(); + mAngularVelocityFunctions.clear(); + + mpVelocityTable.clear(); + mpAngularVelocityTable.clear(); + + for(int i=0; i<3; i++) { + mVelocityIsConstrained[i] = rParameters["velocity_constraints_settings"]["constrained"][i].GetBool(); + mAngularVelocityIsConstrained[i] = rParameters["angular_velocity_constraints_settings"]["constrained"][i].GetBool(); + if(rParameters["velocity_constraints_settings"]["value"][i].IsNull()) { + mVelocityValueIsNumeric[i] = true; + mVelocityValues[i] = 0.0; + mVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + if(rParameters["velocity_constraints_settings"]["value"][i].IsNumber()) { + mVelocityValueIsNumeric[i] = true; + mVelocityValues[i] = rParameters["velocity_constraints_settings"]["value"][i].GetDouble(); + mVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + mVelocityValueIsNumeric[i] = false; + mVelocityFunctions.push_back(PythonGenericFunctionUtility(rParameters["velocity_constraints_settings"]["value"][i].GetString())); + } + } + + if(rParameters["velocity_constraints_settings"]["table"][i].IsNull()) { + mVelocityTableId[i] = 0; + } + else { + mVelocityTableId[i] = rParameters["velocity_constraints_settings"]["table"][i].GetInt(); + } + mpVelocityTable.push_back(mrModelPart.pGetTable(mVelocityTableId[i])); // because I can't construct an array_1d of these + + if(rParameters["angular_velocity_constraints_settings"]["value"][i].IsNull()) { + mAngularVelocityValueIsNumeric[i] = true; + mAngularVelocityValues[i] = 0.0; + mAngularVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + if(rParameters["angular_velocity_constraints_settings"]["value"][i].IsNumber()) { + mAngularVelocityValueIsNumeric[i] = true; + mAngularVelocityValues[i] = rParameters["angular_velocity_constraints_settings"]["value"][i].GetDouble(); + mAngularVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + mAngularVelocityValueIsNumeric[i] = false; + mAngularVelocityFunctions.push_back(PythonGenericFunctionUtility(rParameters["angular_velocity_constraints_settings"]["value"][i].GetString())); + } + } + if(rParameters["angular_velocity_constraints_settings"]["table"][i].IsNull()) { + mAngularVelocityTableId[i] = 0; + } + else { + mAngularVelocityTableId[i] = rParameters["angular_velocity_constraints_settings"]["table"][i].GetInt(); + } + mpAngularVelocityTable.push_back(mrModelPart.pGetTable(mAngularVelocityTableId[i])); // because I can't construct an array_1d of these + } + + mParameters = rParameters; + + KRATOS_CATCH(""); + } + + ApplyKinematicConstraintsProcess::~ApplyKinematicConstraintsProcess() + { + + } + + void ApplyKinematicConstraintsProcess::Execute() + { + } + + void ApplyKinematicConstraintsProcess::ExecuteInitializeSolutionStep() + { + KRATOS_TRY; + + + const double time = mrModelPart.GetProcessInfo()[TIME]; + + if(!mInterval.IsInInterval(time)) return; + + block_for_each(mrModelPart.Nodes(), [&](Node<3>& rNode) + { + + array_1d& vel = rNode.FastGetSolutionStepValue(VELOCITY); + array_1d& ang_vel = rNode.FastGetSolutionStepValue(ANGULAR_VELOCITY); + + if(mVelocityIsConstrained[0]) { + rNode.Set(DEMFlags::FIXED_VEL_X, true); + rNode.pGetDof(VELOCITY_X)->FixDof(); + } + if(mVelocityIsConstrained[1]) { + rNode.Set(DEMFlags::FIXED_VEL_Y, true); + rNode.pGetDof(VELOCITY_Y)->FixDof(); + } + if(mVelocityIsConstrained[2]) { + rNode.Set(DEMFlags::FIXED_VEL_Z, true); + rNode.pGetDof(VELOCITY_Z)->FixDof(); + } + if(mAngularVelocityIsConstrained[0]) { + rNode.Set(DEMFlags::FIXED_ANG_VEL_X, true); + rNode.pGetDof(ANGULAR_VELOCITY_X)->FixDof(); + } + if(mAngularVelocityIsConstrained[1]) { + rNode.Set(DEMFlags::FIXED_ANG_VEL_Y, true); + rNode.pGetDof(ANGULAR_VELOCITY_Y)->FixDof(); + } + if(mAngularVelocityIsConstrained[2]) { + rNode.Set(DEMFlags::FIXED_ANG_VEL_Z, true); + rNode.pGetDof(ANGULAR_VELOCITY_Z)->FixDof(); + } + + for(int i=0; i<3; i++) { + if (mVelocityTableId[i] != 0) { + vel[i] = mpVelocityTable[i]->GetValue(time); + } + else { + if(mVelocityIsConstrained[i]) { + double velocity_value = 0.0; + if(mVelocityValueIsNumeric[i]) { + velocity_value = mVelocityValues[i]; + } + else { + velocity_value = mVelocityFunctions[i].CallFunction(rNode.X(), rNode.Y(), rNode.Z(), time); + } + vel[i] = velocity_value; + } + } + + if (mAngularVelocityTableId[i] != 0) { + ang_vel[i] = mpAngularVelocityTable[i]->GetValue(time); + } + else { + if(mAngularVelocityIsConstrained[i]) { + double angular_velocity_value = 0.0; + if(mAngularVelocityValueIsNumeric[i]) { + angular_velocity_value = mAngularVelocityValues[i]; + } + else { + angular_velocity_value = mAngularVelocityFunctions[i].CallFunction(rNode.X(), rNode.Y(), rNode.Z(), time); + } + ang_vel[i] = angular_velocity_value; + } + } + } + }); + + KRATOS_CATCH(""); + } + + void ApplyKinematicConstraintsProcess::ExecuteFinalizeSolutionStep() + { + KRATOS_TRY; + + + const double time = mrModelPart.GetProcessInfo()[TIME]; + + if(!mInterval.IsInInterval(time)) return; + + block_for_each(mrModelPart.Nodes(), [&](Node<3>& rNode) + { + rNode.Set(DEMFlags::FIXED_VEL_X, false); + rNode.Set(DEMFlags::FIXED_VEL_Y, false); + rNode.Set(DEMFlags::FIXED_VEL_Z, false); + rNode.Set(DEMFlags::FIXED_ANG_VEL_X, false); + rNode.Set(DEMFlags::FIXED_ANG_VEL_Y, false); + rNode.Set(DEMFlags::FIXED_ANG_VEL_Z, false); + rNode.pGetDof(VELOCITY_X)->FreeDof(); + rNode.pGetDof(VELOCITY_Y)->FreeDof(); + rNode.pGetDof(VELOCITY_Z)->FreeDof(); + rNode.pGetDof(ANGULAR_VELOCITY_X)->FreeDof(); + rNode.pGetDof(ANGULAR_VELOCITY_Y)->FreeDof(); + rNode.pGetDof(ANGULAR_VELOCITY_Z)->FreeDof(); + }); + + KRATOS_CATCH(""); + } + + std::string ApplyKinematicConstraintsProcess::Info() const + { + return "ApplyKinematicConstraintsProcess"; + } + + void ApplyKinematicConstraintsProcess::PrintInfo(std::ostream& rOStream) const + { + rOStream << "ApplyKinematicConstraintsProcess"; + } + + void ApplyKinematicConstraintsProcess::PrintData(std::ostream& rOStream) const + { + } + + /* External functions *****************************************************/ + + /// output stream function + inline std::ostream& operator << ( + std::ostream& rOStream, + const ApplyKinematicConstraintsProcess& rThis) + { + rThis.PrintData(rOStream); + return rOStream; + } + +} diff --git a/applications/DEMApplication/custom_processes/apply_kinematic_constraints_process.hpp b/applications/DEMApplication/custom_processes/apply_kinematic_constraints_process.hpp index 0191d7bd084e..4ba97421458b 100644 --- a/applications/DEMApplication/custom_processes/apply_kinematic_constraints_process.hpp +++ b/applications/DEMApplication/custom_processes/apply_kinematic_constraints_process.hpp @@ -1,10 +1,29 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics // -// Author: Miguel Angel Celigueta +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main author: Miguel Angel Celigueta // #if !defined(KRATOS_APPLY_KINEMATIC_CONSTRAINTS_PROCESS ) #define KRATOS_APPLY_KINEMATIC_CONSTRAINTS_PROCESS + + +// System includes +#include +#include + + +// External includes + + +// Project includes #include "includes/table.h" #include "includes/kratos_flags.h" #include "includes/kratos_parameters.h" @@ -15,269 +34,217 @@ namespace Kratos { + ///@addtogroup DEMApplication + ///@{ -class ApplyKinematicConstraintsProcess : public Process -{ + ///@name Kratos Globals + ///@{ -public: + ///@} + ///@name Type Definitions + ///@{ - KRATOS_CLASS_POINTER_DEFINITION(ApplyKinematicConstraintsProcess); + ///@} + ///@name Enum's + ///@{ + ///@} + ///@name Functions + ///@{ -///---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + ///@} + ///@name Kratos Classes + ///@{ - /// Constructor - ApplyKinematicConstraintsProcess(ModelPart& model_part, - Parameters rParameters - ) : Process(Flags()) , mrModelPart(model_part), mParameters(rParameters), mInterval(rParameters) - { - KRATOS_TRY + /// Auxiliary process to apply forces and moments to particles. + /** This process sets the EXTERNAL_APPLIED_FORCE and EXTERNAL_APPLIED_MOMENT variables + over particles. + */ + class ApplyKinematicConstraintsProcess: public Process + { + public: + ///@name Type Definitions + ///@{ - //only include validation with c++11 since raw_literals do not exist in c++03 - Parameters default_parameters( R"( - { - "help" : "This process applies constraints to the particles in a certain submodelpart, for a certain time interval", - "mesh_id" : 0, - "model_part_name" : "please_specify_model_part_name", - "velocity_constraints_settings" : { - "constrained" : [true,true,true], - "value" : [10.0, "3*t", "x+y"] - }, - "angular_velocity_constraints_settings" : { - "constrained" : [true,true,true], - "value" : [10.0, "3*t", "x+y"] - }, - "interval" : [0.0, 1e30] - } )" ); - - - - // Some values need to be mandatorily prescribed since no meaningful default value exist. For this reason try accessing to them - // So that an error is thrown if they don't exist - rParameters["model_part_name"]; - - // Now validate agains defaults -- this also ensures no type mismatch - rParameters.ValidateAndAssignDefaults(default_parameters); - - mVelocityFunctions.clear(); - mAngularVelocityFunctions.clear(); - - for(int i=0; i<3; i++) { - mVelocityIsConstrained[i] = rParameters["velocity_constraints_settings"]["constrained"][i].GetBool(); - mAngularVelocityIsConstrained[i] = rParameters["angular_velocity_constraints_settings"]["constrained"][i].GetBool(); - if(rParameters["velocity_constraints_settings"]["value"][i].IsNumber()) { - mVelocityValueIsNumeric[i] = true; - mVelocityValues[i] = rParameters["velocity_constraints_settings"]["value"][i].GetDouble(); - mVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these - } - else { - mVelocityValueIsNumeric[i] = false; - mVelocityFunctions.push_back(PythonGenericFunctionUtility(rParameters["velocity_constraints_settings"]["value"][i].GetString())); - } - if(rParameters["angular_velocity_constraints_settings"]["value"][i].IsNumber()) { - mAngularVelocityValueIsNumeric[i] = true; - mAngularVelocityValues[i] = rParameters["angular_velocity_constraints_settings"]["value"][i].GetDouble(); - mAngularVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these - } - else { - mAngularVelocityValueIsNumeric[i] = false; - mAngularVelocityFunctions.push_back(PythonGenericFunctionUtility(rParameters["angular_velocity_constraints_settings"]["value"][i].GetString())); - } - } - - mParameters = rParameters; - - KRATOS_CATCH(""); - } - - ///------------------------------------------------------------------------------------ - - /// Destructor - ~ApplyKinematicConstraintsProcess() override {} - -//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - /// Execute method is used to execute the ApplyKinematicConstraintsProcess algorithms. - void Execute() override - { - } - -//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - void ExecuteInitializeSolutionStep() override - { - KRATOS_TRY; - - - const double time = mrModelPart.GetProcessInfo()[TIME]; - - if(!mInterval.IsInInterval(time)) return; - - const int nnodes = static_cast(mrModelPart.Nodes().size()); - - if(nnodes != 0) - { - ModelPart::NodesContainerType::iterator it_begin = mrModelPart.NodesBegin(); - - #pragma omp parallel for - for(int i = 0; i& vel = it_node->FastGetSolutionStepValue(VELOCITY); - array_1d& ang_vel = it_node->FastGetSolutionStepValue(ANGULAR_VELOCITY); - - if(mVelocityIsConstrained[0]) { - it_node->Set(DEMFlags::FIXED_VEL_X, true); - it_node->pGetDof(VELOCITY_X)->FixDof(); - } - if(mVelocityIsConstrained[1]) { - it_node->Set(DEMFlags::FIXED_VEL_Y, true); - it_node->pGetDof(VELOCITY_Y)->FixDof(); - } - if(mVelocityIsConstrained[2]) { - it_node->Set(DEMFlags::FIXED_VEL_Z, true); - it_node->pGetDof(VELOCITY_Z)->FixDof(); - } - if(mAngularVelocityIsConstrained[0]) { - it_node->Set(DEMFlags::FIXED_ANG_VEL_X, true); - it_node->pGetDof(ANGULAR_VELOCITY_X)->FixDof(); - } - if(mAngularVelocityIsConstrained[1]) { - it_node->Set(DEMFlags::FIXED_ANG_VEL_Y, true); - it_node->pGetDof(ANGULAR_VELOCITY_Y)->FixDof(); - } - if(mAngularVelocityIsConstrained[2]) { - it_node->Set(DEMFlags::FIXED_ANG_VEL_Z, true); - it_node->pGetDof(ANGULAR_VELOCITY_Z)->FixDof(); - } - - for(int i=0; i<3; i++) { - if(mVelocityIsConstrained[i]) { - double velocity_value = 0.0; - if(mVelocityValueIsNumeric[i]) { - velocity_value = mVelocityValues[i]; - } - else { - velocity_value = mVelocityFunctions[i].CallFunction(it_node->X(), it_node->Y(), it_node->Z(), time); - } - vel[i] = velocity_value; - } - if(mAngularVelocityIsConstrained[i]) { - double angular_velocity_value = 0.0; - if(mAngularVelocityValueIsNumeric[i]) { - angular_velocity_value = mAngularVelocityValues[i]; - } - else { - angular_velocity_value = mAngularVelocityFunctions[i].CallFunction(it_node->X(), it_node->Y(), it_node->Z(), time); - } - ang_vel[i] = angular_velocity_value; - } - } - } - } - - KRATOS_CATCH(""); - } - - void ExecuteFinalizeSolutionStep() override - { - KRATOS_TRY; - - - const double time = mrModelPart.GetProcessInfo()[TIME]; - - if(!mInterval.IsInInterval(time)) return; - - const int nnodes = static_cast(mrModelPart.Nodes().size()); - - if(nnodes != 0) - { - ModelPart::NodesContainerType::iterator it_begin = mrModelPart.NodesBegin(); - - #pragma omp parallel for - for(int i = 0; iSet(DEMFlags::FIXED_VEL_X, false); - it_node->Set(DEMFlags::FIXED_VEL_Y, false); - it_node->Set(DEMFlags::FIXED_VEL_Z, false); - it_node->Set(DEMFlags::FIXED_ANG_VEL_X, false); - it_node->Set(DEMFlags::FIXED_ANG_VEL_Y, false); - it_node->Set(DEMFlags::FIXED_ANG_VEL_Z, false); - it_node->pGetDof(VELOCITY_X)->FreeDof(); - it_node->pGetDof(VELOCITY_Y)->FreeDof(); - it_node->pGetDof(VELOCITY_Z)->FreeDof(); - it_node->pGetDof(ANGULAR_VELOCITY_X)->FreeDof(); - it_node->pGetDof(ANGULAR_VELOCITY_Y)->FreeDof(); - it_node->pGetDof(ANGULAR_VELOCITY_Z)->FreeDof(); - } - } - - KRATOS_CATCH(""); - } - - /// Turn back information as a string. - std::string Info() const override - { - return "ApplyKinematicConstraintsProcess"; - } - - /// Print information about this object. - void PrintInfo(std::ostream& rOStream) const override - { - rOStream << "ApplyKinematicConstraintsProcess"; - } - - /// Print object's data. - void PrintData(std::ostream& rOStream) const override - { - } - -///---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -protected: - - /// Member Variables - - ModelPart& mrModelPart; - Parameters mParameters; - IntervalUtility mInterval; - array_1d mVelocityIsConstrained; - array_1d mAngularVelocityIsConstrained; - array_1d mVelocityValueIsNumeric; - array_1d mAngularVelocityValueIsNumeric; - array_1d mVelocityValues; - array_1d mAngularVelocityValues; - std::vector mVelocityFunctions; - std::vector mAngularVelocityFunctions; - - -///---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -private: - - /// Assignment operator. - ApplyKinematicConstraintsProcess& operator=(ApplyKinematicConstraintsProcess const& rOther); - - /// Copy constructor. - //ApplyKinematicConstraintsProcess(ApplyKinematicConstraintsProcess const& rOther); - -}; // Class ApplyKinematicConstraintsProcess - -/// input stream function -inline std::istream& operator >> (std::istream& rIStream, - ApplyKinematicConstraintsProcess& rThis); - -/// output stream function -inline std::ostream& operator << (std::ostream& rOStream, - const ApplyKinematicConstraintsProcess& rThis) -{ - rThis.PrintInfo(rOStream); - rOStream << std::endl; - rThis.PrintData(rOStream); + /// Pointer definition of ApplyKinematicConstraintsProcess + KRATOS_CLASS_POINTER_DEFINITION(ApplyKinematicConstraintsProcess); + + /// Defining a table with double argument and result type as table type. + typedef Table TableType; + + ///@} + ///@name Life Cycle + ///@{ + + /// Constructor + ApplyKinematicConstraintsProcess(ModelPart& rModelPart, Parameters rParameters); + + /// Destructor. + ~ApplyKinematicConstraintsProcess() override; + + + ///@} + ///@name Operators + ///@{ + + + ///@} + ///@name Operations + ///@{ + + void Execute() override; + + void ExecuteInitializeSolutionStep() override; + + void ExecuteFinalizeSolutionStep() override; + + ///@} + ///@name Access + ///@{ + + + ///@} + ///@name Inquiry + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + /// Turn back information as a string. + std::string Info() const override; + + /// Print information about this object. + void PrintInfo(std::ostream& rOStream) const override; + + /// Print object's data. + void PrintData(std::ostream& rOStream) const override; + + + ///@} + ///@name Friends + ///@{ + + + ///@} + + protected: + ///@name Protected static Member Variables + ///@{ + + + ///@} + ///@name Protected member Variables + ///@{ + + + ///@} + ///@name Protected Operators + ///@{ + + + ///@} + ///@name Protected Operations + ///@{ + + ///@} + ///@name Protected Access + ///@{ + + + ///@} + ///@name Protected Inquiry + ///@{ + + + ///@} + ///@name Protected LifeCycle + ///@{ + + + ///@} + + private: + ///@name Static Member Variables + ///@{ + + + ///@} + ///@name Member Variables + ///@{ + + ModelPart& mrModelPart; + Parameters mParameters; + IntervalUtility mInterval; + array_1d mVelocityIsConstrained; + array_1d mAngularVelocityIsConstrained; + array_1d mVelocityValueIsNumeric; + array_1d mAngularVelocityValueIsNumeric; + array_1d mVelocityValues; + array_1d mAngularVelocityValues; + std::vector mVelocityFunctions; + std::vector mAngularVelocityFunctions; + array_1d mVelocityTableId; + array_1d mAngularVelocityTableId; + std::vector mpVelocityTable; + std::vector mpAngularVelocityTable; + + ///@} + ///@name Private Operators + ///@{ + + + ///@} + ///@name Private Operations + ///@{ + + + ///@} + ///@name Private Access + ///@{ + + + ///@} + ///@name Private Inquiry + ///@{ + + + ///@} + ///@name Un accessible methods + ///@{ + + /// Assignment operator. + ApplyKinematicConstraintsProcess& operator=(ApplyKinematicConstraintsProcess const& rOther); + + /// Copy constructor. + ApplyKinematicConstraintsProcess(ApplyKinematicConstraintsProcess const& rOther); + + + ///@} + + }; // Class ApplyKinematicConstraintsProcess + + ///@} + + ///@name Type Definitions + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + + /// output stream function + inline std::ostream& operator << ( + std::ostream& rOStream, + const ApplyKinematicConstraintsProcess& rThis); + + ///@} - return rOStream; -} + ///@} addtogroup block -} // namespace Kratos. +} // namespace Kratos. -#endif /* KRATOS_APPLY_KINEMATIC_CONSTRAINTS_PROCESS defined */ +#endif // KRATOS_APPLY_KINEMATIC_CONSTRAINTS_PROCESS defined diff --git a/applications/DEMApplication/custom_processes/apply_kinematic_constraints_to_walls_process.cpp b/applications/DEMApplication/custom_processes/apply_kinematic_constraints_to_walls_process.cpp new file mode 100644 index 000000000000..f66957ef1552 --- /dev/null +++ b/applications/DEMApplication/custom_processes/apply_kinematic_constraints_to_walls_process.cpp @@ -0,0 +1,247 @@ +#include "apply_kinematic_constraints_to_walls_process.hpp" +#include "utilities/parallel_utilities.h" + +namespace Kratos +{ + /* Public functions *******************************************************/ + ApplyKinematicConstraintsToWallsProcess::ApplyKinematicConstraintsToWallsProcess( + ModelPart& rModelPart, + Parameters rParameters + ) : Process(Flags()) , mrModelPart(rModelPart), mParameters(rParameters), mInterval(rParameters) + { + KRATOS_TRY + + //only include validation with c++11 since raw_literals do not exist in c++03 + Parameters default_parameters( R"( + { + "help" : "This process applies constraints to the rigid walls in a certain submodelpart, for a certain time interval", + "mesh_id" : 0, + "model_part_name" : "please_specify_model_part_name", + "velocity_constraints_settings" : { + "constrained" : [true,true,true], + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "angular_velocity_constraints_settings" : { + "constrained" : [true,true,true], + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "interval" : [0.0, 1e30] + } )" ); + + + + // Some values need to be mandatorily prescribed since no meaningful default value exist. For this reason try accessing to them + // So that an error is thrown if they don't exist + rParameters["model_part_name"]; + + // Now validate agains defaults -- this also ensures no type mismatch + rParameters.ValidateAndAssignDefaults(default_parameters); + + mVelocityFunctions.clear(); + mAngularVelocityFunctions.clear(); + + mpVelocityTable.clear(); + mpAngularVelocityTable.clear(); + + for(int i=0; i<3; i++) { + mVelocityIsConstrained[i] = rParameters["velocity_constraints_settings"]["constrained"][i].GetBool(); + mAngularVelocityIsConstrained[i] = rParameters["angular_velocity_constraints_settings"]["constrained"][i].GetBool(); + if(rParameters["velocity_constraints_settings"]["value"][i].IsNull()) { + mVelocityValueIsNumeric[i] = true; + mVelocityValues[i] = 0.0; + mVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + if(rParameters["velocity_constraints_settings"]["value"][i].IsNumber()) { + mVelocityValueIsNumeric[i] = true; + mVelocityValues[i] = rParameters["velocity_constraints_settings"]["value"][i].GetDouble(); + mVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + mVelocityValueIsNumeric[i] = false; + mVelocityFunctions.push_back(PythonGenericFunctionUtility(rParameters["velocity_constraints_settings"]["value"][i].GetString())); + } + } + + if(rParameters["velocity_constraints_settings"]["table"][i].IsNull()) { + mVelocityTableId[i] = 0; + } + else { + mVelocityTableId[i] = rParameters["velocity_constraints_settings"]["table"][i].GetInt(); + } + mpVelocityTable.push_back(mrModelPart.pGetTable(mVelocityTableId[i])); // because I can't construct an array_1d of these + + if(rParameters["angular_velocity_constraints_settings"]["value"][i].IsNull()) { + mAngularVelocityValueIsNumeric[i] = true; + mAngularVelocityValues[i] = 0.0; + mAngularVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + if(rParameters["angular_velocity_constraints_settings"]["value"][i].IsNumber()) { + mAngularVelocityValueIsNumeric[i] = true; + mAngularVelocityValues[i] = rParameters["angular_velocity_constraints_settings"]["value"][i].GetDouble(); + mAngularVelocityFunctions.push_back(PythonGenericFunctionUtility("0.0")); // because I can't construct an array_1d of these + } + else { + mAngularVelocityValueIsNumeric[i] = false; + mAngularVelocityFunctions.push_back(PythonGenericFunctionUtility(rParameters["angular_velocity_constraints_settings"]["value"][i].GetString())); + } + } + if(rParameters["angular_velocity_constraints_settings"]["table"][i].IsNull()) { + mAngularVelocityTableId[i] = 0; + } + else { + mAngularVelocityTableId[i] = rParameters["angular_velocity_constraints_settings"]["table"][i].GetInt(); + } + mpAngularVelocityTable.push_back(mrModelPart.pGetTable(mAngularVelocityTableId[i])); // because I can't construct an array_1d of these + } + + mParameters = rParameters; + + KRATOS_CATCH(""); + } + + ApplyKinematicConstraintsToWallsProcess::~ApplyKinematicConstraintsToWallsProcess() + { + + } + + void ApplyKinematicConstraintsToWallsProcess::Execute() + { + } + + void ApplyKinematicConstraintsToWallsProcess::ExecuteInitializeSolutionStep() + { + KRATOS_TRY; + + + const double time = mrModelPart.GetProcessInfo()[TIME]; + + if(!mInterval.IsInInterval(time)) return; + + block_for_each(mrModelPart.Elements(), [&](Element& rElement) + { + + array_1d& vel = rElement.GetGeometry()[0].FastGetSolutionStepValue(VELOCITY); + array_1d& ang_vel = rElement.GetGeometry()[0].FastGetSolutionStepValue(ANGULAR_VELOCITY); + + if(mVelocityIsConstrained[0]) { + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_VEL_X, true); + rElement.GetGeometry()[0].pGetDof(VELOCITY_X)->FixDof(); + } + if(mVelocityIsConstrained[1]) { + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_VEL_Y, true); + rElement.GetGeometry()[0].pGetDof(VELOCITY_Y)->FixDof(); + } + if(mVelocityIsConstrained[2]) { + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_VEL_Z, true); + rElement.GetGeometry()[0].pGetDof(VELOCITY_Z)->FixDof(); + } + if(mAngularVelocityIsConstrained[0]) { + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_ANG_VEL_X, true); + rElement.GetGeometry()[0].pGetDof(ANGULAR_VELOCITY_X)->FixDof(); + } + if(mAngularVelocityIsConstrained[1]) { + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_ANG_VEL_Y, true); + rElement.GetGeometry()[0].pGetDof(ANGULAR_VELOCITY_Y)->FixDof(); + } + if(mAngularVelocityIsConstrained[2]) { + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_ANG_VEL_Z, true); + rElement.GetGeometry()[0].pGetDof(ANGULAR_VELOCITY_Z)->FixDof(); + } + + for(int i=0; i<3; i++) { + if (mVelocityTableId[i] != 0) { + vel[i] = mpVelocityTable[i]->GetValue(time); + } + else { + if(mVelocityIsConstrained[i]) { + double velocity_value = 0.0; + if(mVelocityValueIsNumeric[i]) { + velocity_value = mVelocityValues[i]; + } + else { + velocity_value = mVelocityFunctions[i].CallFunction(rElement.GetGeometry()[0].X(), rElement.GetGeometry()[0].Y(), rElement.GetGeometry()[0].Z(), time); + } + vel[i] = velocity_value; + } + } + + if (mAngularVelocityTableId[i] != 0) { + ang_vel[i] = mpAngularVelocityTable[i]->GetValue(time); + } + else { + if(mAngularVelocityIsConstrained[i]) { + double angular_velocity_value = 0.0; + if(mAngularVelocityValueIsNumeric[i]) { + angular_velocity_value = mAngularVelocityValues[i]; + } + else { + angular_velocity_value = mAngularVelocityFunctions[i].CallFunction(rElement.GetGeometry()[0].X(), rElement.GetGeometry()[0].Y(), rElement.GetGeometry()[0].Z(), time); + } + ang_vel[i] = angular_velocity_value; + } + } + } + }); + + KRATOS_CATCH(""); + } + + void ApplyKinematicConstraintsToWallsProcess::ExecuteFinalizeSolutionStep() + { + KRATOS_TRY; + + + const double time = mrModelPart.GetProcessInfo()[TIME]; + + if(!mInterval.IsInInterval(time)) return; + + block_for_each(mrModelPart.Elements(), [&](Element& rElement) + { + + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_VEL_X, false); + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_VEL_Y, false); + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_VEL_Z, false); + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_ANG_VEL_X, false); + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_ANG_VEL_Y, false); + rElement.GetGeometry()[0].Set(DEMFlags::FIXED_ANG_VEL_Z, false); + rElement.GetGeometry()[0].pGetDof(VELOCITY_X)->FreeDof(); + rElement.GetGeometry()[0].pGetDof(VELOCITY_Y)->FreeDof(); + rElement.GetGeometry()[0].pGetDof(VELOCITY_Z)->FreeDof(); + rElement.GetGeometry()[0].pGetDof(ANGULAR_VELOCITY_X)->FreeDof(); + rElement.GetGeometry()[0].pGetDof(ANGULAR_VELOCITY_Y)->FreeDof(); + rElement.GetGeometry()[0].pGetDof(ANGULAR_VELOCITY_Z)->FreeDof(); + }); + + KRATOS_CATCH(""); + } + + std::string ApplyKinematicConstraintsToWallsProcess::Info() const + { + return "ApplyKinematicConstraintsToWallsProcess"; + } + + void ApplyKinematicConstraintsToWallsProcess::PrintInfo(std::ostream& rOStream) const + { + rOStream << "ApplyKinematicConstraintsToWallsProcess"; + } + + void ApplyKinematicConstraintsToWallsProcess::PrintData(std::ostream& rOStream) const + { + } + + /* External functions *****************************************************/ + + /// output stream function + inline std::ostream& operator << ( + std::ostream& rOStream, + const ApplyKinematicConstraintsToWallsProcess& rThis) + { + rThis.PrintData(rOStream); + return rOStream; + } + +} diff --git a/applications/DEMApplication/custom_processes/apply_kinematic_constraints_to_walls_process.hpp b/applications/DEMApplication/custom_processes/apply_kinematic_constraints_to_walls_process.hpp new file mode 100644 index 000000000000..1274732c6385 --- /dev/null +++ b/applications/DEMApplication/custom_processes/apply_kinematic_constraints_to_walls_process.hpp @@ -0,0 +1,250 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main author: Joaquín Irazábal González +// + +#if !defined(KRATOS_APPLY_KINEMATIC_CONSTRAINTS_TO_WALLS_PROCESS ) +#define KRATOS_APPLY_KINEMATIC_CONSTRAINTS_TO_WALLS_PROCESS + + + +// System includes +#include +#include + + +// External includes + + +// Project includes +#include "includes/table.h" +#include "includes/kratos_flags.h" +#include "includes/kratos_parameters.h" +#include "processes/process.h" +#include "utilities/interval_utility.h" +#include "utilities/python_function_callback_utility.h" +#include "DEM_application_variables.h" + +namespace Kratos +{ + ///@addtogroup DEMApplication + ///@{ + + ///@name Kratos Globals + ///@{ + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Enum's + ///@{ + + ///@} + ///@name Functions + ///@{ + + ///@} + ///@name Kratos Classes + ///@{ + + /// Auxiliary process to apply forces and moments to particles. + /** This process sets the EXTERNAL_APPLIED_FORCE and EXTERNAL_APPLIED_MOMENT variables + over particles. + */ + class ApplyKinematicConstraintsToWallsProcess: public Process + { + public: + ///@name Type Definitions + ///@{ + + /// Pointer definition of ApplyKinematicConstraintsToWallsProcess + KRATOS_CLASS_POINTER_DEFINITION(ApplyKinematicConstraintsToWallsProcess); + + /// Defining a table with double argument and result type as table type. + typedef Table TableType; + + ///@} + ///@name Life Cycle + ///@{ + + /// Constructor + ApplyKinematicConstraintsToWallsProcess(ModelPart& rModelPart, Parameters rParameters); + + /// Destructor. + ~ApplyKinematicConstraintsToWallsProcess() override; + + + ///@} + ///@name Operators + ///@{ + + + ///@} + ///@name Operations + ///@{ + + void Execute() override; + + void ExecuteInitializeSolutionStep() override; + + void ExecuteFinalizeSolutionStep() override; + + ///@} + ///@name Access + ///@{ + + + ///@} + ///@name Inquiry + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + /// Turn back information as a string. + std::string Info() const override; + + /// Print information about this object. + void PrintInfo(std::ostream& rOStream) const override; + + /// Print object's data. + void PrintData(std::ostream& rOStream) const override; + + + ///@} + ///@name Friends + ///@{ + + + ///@} + + protected: + ///@name Protected static Member Variables + ///@{ + + + ///@} + ///@name Protected member Variables + ///@{ + + + ///@} + ///@name Protected Operators + ///@{ + + + ///@} + ///@name Protected Operations + ///@{ + + ///@} + ///@name Protected Access + ///@{ + + + ///@} + ///@name Protected Inquiry + ///@{ + + + ///@} + ///@name Protected LifeCycle + ///@{ + + + ///@} + + private: + ///@name Static Member Variables + ///@{ + + + ///@} + ///@name Member Variables + ///@{ + + ModelPart& mrModelPart; + Parameters mParameters; + IntervalUtility mInterval; + array_1d mVelocityIsConstrained; + array_1d mAngularVelocityIsConstrained; + array_1d mVelocityValueIsNumeric; + array_1d mAngularVelocityValueIsNumeric; + array_1d mVelocityValues; + array_1d mAngularVelocityValues; + std::vector mVelocityFunctions; + std::vector mAngularVelocityFunctions; + array_1d mVelocityTableId; + array_1d mAngularVelocityTableId; + std::vector mpVelocityTable; + std::vector mpAngularVelocityTable; + + ///@} + ///@name Private Operators + ///@{ + + + ///@} + ///@name Private Operations + ///@{ + + + ///@} + ///@name Private Access + ///@{ + + + ///@} + ///@name Private Inquiry + ///@{ + + + ///@} + ///@name Un accessible methods + ///@{ + + /// Assignment operator. + ApplyKinematicConstraintsToWallsProcess& operator=(ApplyKinematicConstraintsToWallsProcess const& rOther); + + /// Copy constructor. + ApplyKinematicConstraintsToWallsProcess(ApplyKinematicConstraintsToWallsProcess const& rOther); + + + ///@} + + }; // Class ApplyKinematicConstraintsToWallsProcess + + ///@} + + ///@name Type Definitions + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + + /// output stream function + inline std::ostream& operator << ( + std::ostream& rOStream, + const ApplyKinematicConstraintsToWallsProcess& rThis); + + ///@} + + ///@} addtogroup block + +} // namespace Kratos. + +#endif // KRATOS_APPLY_KINEMATIC_CONSTRAINTS_TO_WALLS_PROCESS defined diff --git a/applications/DEMApplication/custom_python/DEM_python_application.cpp b/applications/DEMApplication/custom_python/DEM_python_application.cpp index 5eeeecf2fe58..35e9e55c8276 100755 --- a/applications/DEMApplication/custom_python/DEM_python_application.cpp +++ b/applications/DEMApplication/custom_python/DEM_python_application.cpp @@ -62,7 +62,6 @@ PYBIND11_MODULE(KratosDEMApplication,m) KRATOS_REGISTER_IN_PYTHON_3D_VARIABLE_WITH_COMPONENTS(m, TABLE_NUMBER_ANGULAR_VELOCITY) KRATOS_REGISTER_IN_PYTHON_3D_VARIABLE_WITH_COMPONENTS(m, TABLE_NUMBER_FORCE) KRATOS_REGISTER_IN_PYTHON_3D_VARIABLE_WITH_COMPONENTS(m, TABLE_NUMBER_MOMENT) - KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, TABLE_NUMBER) // JIG: To erase (1 January 2019) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, BOUNDING_BOX_OPTION) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, ROTATION_OPTION) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, CRITICAL_TIME_OPTION) @@ -154,6 +153,7 @@ PYBIND11_MODULE(KratosDEMApplication,m) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, FRICTION) //deprecated since April 6th, 2020 KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, STATIC_FRICTION) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, DYNAMIC_FRICTION) + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, FRICTION_DECAY) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, COEFFICIENT_OF_RESTITUTION) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, PARTICLE_ROTATION_DAMP_RATIO) KRATOS_REGISTER_IN_PYTHON_VARIABLE(m, DAMPING_GAMMA) diff --git a/applications/DEMApplication/custom_python/add_custom_processes_to_python.cpp b/applications/DEMApplication/custom_python/add_custom_processes_to_python.cpp index d4444685f9f8..fc0598d18e4c 100755 --- a/applications/DEMApplication/custom_python/add_custom_processes_to_python.cpp +++ b/applications/DEMApplication/custom_python/add_custom_processes_to_python.cpp @@ -21,6 +21,9 @@ // Processes #include "custom_processes/apply_kinematic_constraints_process.hpp" +#include "custom_processes/apply_kinematic_constraints_to_walls_process.hpp" +#include "custom_processes/apply_forces_and_moments_process.hpp" +#include "custom_processes/apply_forces_and_moments_to_walls_process.hpp" #include "custom_processes/control_module_2d_process.hpp" #include "custom_processes/automatic_dt_process.hpp" @@ -40,6 +43,18 @@ void AddCustomProcessesToPython(pybind11::module& m) (m, "ApplyKinematicConstraintsProcess") .def(py::init < ModelPart&, Parameters>()); + py::class_ + (m, "ApplyKinematicConstraintsToWallsProcess") + .def(py::init < ModelPart&, Parameters>()); + + py::class_ + (m, "ApplyForcesAndMomentsProcess") + .def(py::init < ModelPart&, Parameters >()); + + py::class_ + (m, "ApplyForcesAndMomentsToWallsProcess") + .def(py::init < ModelPart&, Parameters >()); + py::class_ (m, "ControlModule2DProcess") .def( py::init< ModelPart&, Parameters>()); diff --git a/applications/DEMApplication/custom_python/add_custom_utilities_to_python.cpp b/applications/DEMApplication/custom_python/add_custom_utilities_to_python.cpp index d81cba9df934..6138eb24fcef 100755 --- a/applications/DEMApplication/custom_python/add_custom_utilities_to_python.cpp +++ b/applications/DEMApplication/custom_python/add_custom_utilities_to_python.cpp @@ -178,6 +178,7 @@ void AddCustomUtilitiesToPython(pybind11::module& m) { py::class_(m, "DEM_Inlet") .def(py::init()) + .def(py::init()) .def("CreateElementsFromInletMesh", &DEM_Inlet::CreateElementsFromInletMesh) .def("InitializeDEM_Inlet", &DEM_Inlet::InitializeDEM_Inlet ,py::arg("model_part") @@ -188,6 +189,7 @@ void AddCustomUtilitiesToPython(pybind11::module& m) { ; py::class_(m, "DEM_Force_Based_Inlet") + .def(py::init, const int>()) .def(py::init>()) ; @@ -328,6 +330,7 @@ void AddCustomUtilitiesToPython(pybind11::module& m) { py::class_(m, "AuxiliaryUtilities") .def(py::init<>()) .def("ComputeAverageZStressFor2D", &AuxiliaryUtilities::ComputeAverageZStressFor2D) + .def("UpdateTimeInOneModelPart", &AuxiliaryUtilities::UpdateTimeInOneModelPart) ; py::class_(m, "PropertiesProxiesManager") diff --git a/applications/DEMApplication/custom_strategies/strategies/explicit_solver_strategy.cpp b/applications/DEMApplication/custom_strategies/strategies/explicit_solver_strategy.cpp index 0fa8cbc8a0a3..7acfb855c207 100644 --- a/applications/DEMApplication/custom_strategies/strategies/explicit_solver_strategy.cpp +++ b/applications/DEMApplication/custom_strategies/strategies/explicit_solver_strategy.cpp @@ -867,6 +867,7 @@ namespace Kratos { RigidBodyElement3D* rigid_body_element = dynamic_cast(RigidBodyElement3D_Kratos.get()); fem_model_part.AddElement(RigidBodyElement3D_Kratos); //, Element_Id + 1); + submp.AddElement(RigidBodyElement3D_Kratos); //, Element_Id + 1); std::size_t element_id = Element_Id_1 + 1; std::vector ElementIds; @@ -1268,6 +1269,18 @@ namespace Kratos { rigid_body_element.GetGeometry()[0].Set(DEMFlags::FIXED_ANG_VEL_Z, true); } + if (submp.Has(EXTERNAL_APPLIED_FORCE)) { // JIG: Backward compatibility, it should be removed in the future + rigid_body_element.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_FORCE)[0] = submp[EXTERNAL_APPLIED_FORCE][0]; + rigid_body_element.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_FORCE)[1] = submp[EXTERNAL_APPLIED_FORCE][1]; + rigid_body_element.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_FORCE)[2] = submp[EXTERNAL_APPLIED_FORCE][2]; + } + + if (submp.Has(EXTERNAL_APPLIED_MOMENT)) { // JIG: Backward compatibility, it should be removed in the future + rigid_body_element.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_MOMENT)[0] = submp[EXTERNAL_APPLIED_MOMENT][0]; + rigid_body_element.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_MOMENT)[1] = submp[EXTERNAL_APPLIED_MOMENT][1]; + rigid_body_element.GetGeometry()[0].FastGetSolutionStepValue(EXTERNAL_APPLIED_MOMENT)[2] = submp[EXTERNAL_APPLIED_MOMENT][2]; + } + if (submp.Has(TABLE_NUMBER_FORCE)) { // JIG: Backward compatibility, it should be removed in the future if (submp[TABLE_NUMBER_FORCE][0] != 0) { const int table_number = submp[TABLE_NUMBER_FORCE][0]; diff --git a/applications/DEMApplication/custom_utilities/AuxiliaryUtilities.cpp b/applications/DEMApplication/custom_utilities/AuxiliaryUtilities.cpp index d61f740e3fe3..346f48a06c3a 100644 --- a/applications/DEMApplication/custom_utilities/AuxiliaryUtilities.cpp +++ b/applications/DEMApplication/custom_utilities/AuxiliaryUtilities.cpp @@ -12,5 +12,12 @@ namespace Kratos { + void AuxiliaryUtilities::UpdateTimeInOneModelPart(ModelPart& r_model_part, const double& time, const double& dt, const bool& is_time_to_print){ + auto& process_info = r_model_part.GetProcessInfo(); + process_info[TIME] = time; + process_info[DELTA_TIME] = dt; + process_info[TIME_STEPS] += 1; + process_info[IS_TIME_TO_PRINT] = is_time_to_print; + }; -} // Namespace Kratos +} // Namespace Kratos \ No newline at end of file diff --git a/applications/DEMApplication/custom_utilities/AuxiliaryUtilities.h b/applications/DEMApplication/custom_utilities/AuxiliaryUtilities.h index f261e82cce29..3e11540aaac5 100644 --- a/applications/DEMApplication/custom_utilities/AuxiliaryUtilities.h +++ b/applications/DEMApplication/custom_utilities/AuxiliaryUtilities.h @@ -23,6 +23,8 @@ namespace Kratos { AuxiliaryUtilities() {}; virtual ~AuxiliaryUtilities() {}; + void UpdateTimeInOneModelPart(ModelPart& r_model_part, const double& time, const double& dt, const bool& is_time_to_print); + double ComputeAverageZStressFor2D(ModelPart& rSpheresModelPart) { ElementsArrayType& pElements = rSpheresModelPart.GetCommunicator().LocalMesh().Elements(); diff --git a/applications/DEMApplication/custom_utilities/GeometryFunctions.h b/applications/DEMApplication/custom_utilities/GeometryFunctions.h index 0b9d695c2cf8..34bb03b830d1 100644 --- a/applications/DEMApplication/custom_utilities/GeometryFunctions.h +++ b/applications/DEMApplication/custom_utilities/GeometryFunctions.h @@ -1315,6 +1315,20 @@ namespace Kratos { return false; }//VertexCheck + + static inline bool FastVertexCheck(const array_1d& Coord, const array_1d& Particle_Coord, double Radius) + { + double dist_sq = 0.0; + array_1d normal_v; + for (unsigned int j = 0; j < 3; j++) + { + normal_v[j] = Particle_Coord[j] - Coord[j]; + dist_sq += normal_v[j] * normal_v[j]; + } + if (dist_sq <= Radius * Radius) return true; + return false; + }//FastVertexCheck + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////******The four Functions BELOW are used to calculate the weight coefficient for quadrilateral*******/////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/applications/DEMApplication/custom_utilities/force_based_inlet.cpp b/applications/DEMApplication/custom_utilities/force_based_inlet.cpp index 80cef56a2068..bbabf8394d48 100644 --- a/applications/DEMApplication/custom_utilities/force_based_inlet.cpp +++ b/applications/DEMApplication/custom_utilities/force_based_inlet.cpp @@ -6,8 +6,8 @@ namespace Kratos { -DEM_Force_Based_Inlet::DEM_Force_Based_Inlet(ModelPart& inlet_modelpart, array_1d injection_force): - DEM_Inlet(inlet_modelpart), mInjectionForce(injection_force) +DEM_Force_Based_Inlet::DEM_Force_Based_Inlet(ModelPart& inlet_modelpart, array_1d injection_force, const int seed): + DEM_Inlet(inlet_modelpart, seed), mInjectionForce(injection_force) {} void DEM_Force_Based_Inlet::RemoveInjectionConditions(Element &element, int dimension) diff --git a/applications/DEMApplication/custom_utilities/force_based_inlet.h b/applications/DEMApplication/custom_utilities/force_based_inlet.h index b120c25099cd..b90fccff93d4 100644 --- a/applications/DEMApplication/custom_utilities/force_based_inlet.h +++ b/applications/DEMApplication/custom_utilities/force_based_inlet.h @@ -18,7 +18,7 @@ namespace Kratos { KRATOS_CLASS_POINTER_DEFINITION(DEM_Force_Based_Inlet); /// Constructor: - DEM_Force_Based_Inlet(ModelPart& inlet_modelpart, array_1d injection_force); + DEM_Force_Based_Inlet(ModelPart& inlet_modelpart, array_1d injection_force, const int seed=42); /// Destructor. virtual ~DEM_Force_Based_Inlet(){} diff --git a/applications/DEMApplication/custom_utilities/inlet.cpp b/applications/DEMApplication/custom_utilities/inlet.cpp index ffd67f58ef2d..126f8fe8390e 100644 --- a/applications/DEMApplication/custom_utilities/inlet.cpp +++ b/applications/DEMApplication/custom_utilities/inlet.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "inlet.h" #include "create_and_destroy.h" @@ -41,7 +42,7 @@ namespace Kratos { /// Constructor - DEM_Inlet::DEM_Inlet(ModelPart& inlet_modelpart): mInletModelPart(inlet_modelpart) + DEM_Inlet::DEM_Inlet(ModelPart& inlet_modelpart, const int seed): mInletModelPart(inlet_modelpart) { const int number_of_submodelparts = inlet_modelpart.NumberOfSubModelParts(); mPartialParticleToInsert.resize(number_of_submodelparts); @@ -51,6 +52,9 @@ namespace Kratos { mNumberOfParticlesInjected.resize(number_of_submodelparts); mMassInjected.resize(number_of_submodelparts); + std::mt19937 gen(seed); + mGenerator = gen; + int smp_iterator_number = 0; for (ModelPart::SubModelPartsContainerType::iterator sub_model_part = inlet_modelpart.SubModelPartsBegin(); sub_model_part != inlet_modelpart.SubModelPartsEnd(); ++sub_model_part) { mPartialParticleToInsert[smp_iterator_number] = 0.0; @@ -544,8 +548,6 @@ namespace Kratos { } if (number_of_particles_to_insert) { - //randomizing mesh - std::mt19937 random_generator(r_modelpart.GetProcessInfo()[TIME_STEPS]); ModelPart::ElementsContainerType::ContainerType valid_elements(mesh_size_elements); //This is a new vector we are going to work on int valid_elements_length = 0; @@ -610,7 +612,8 @@ namespace Kratos { } } - int random_pos = random_generator() % valid_elements_length; + int random_pos = mGenerator() % valid_elements_length; + Element* p_injector_element = valid_elements[random_pos].get(); if (mp[CONTAINS_CLUSTERS] == false) { diff --git a/applications/DEMApplication/custom_utilities/inlet.h b/applications/DEMApplication/custom_utilities/inlet.h index 37ced64abdc9..e1f4a9746903 100644 --- a/applications/DEMApplication/custom_utilities/inlet.h +++ b/applications/DEMApplication/custom_utilities/inlet.h @@ -9,6 +9,7 @@ // System includes #include #include +#include // External includes @@ -46,7 +47,7 @@ namespace Kratos { KRATOS_CLASS_POINTER_DEFINITION(DEM_Inlet); /// Constructor: - DEM_Inlet(ModelPart& inlet_modelpart); + DEM_Inlet(ModelPart& inlet_modelpart, const int seed=42); /// Destructor. virtual ~DEM_Inlet(){} @@ -96,7 +97,9 @@ namespace Kratos { std::vector mNumberOfParticlesInjected; std::map mOriginInletSubmodelPartIndexes; double mTotalMassInjected; + //int mSeed; std::vector mMassInjected; + std::mt19937 mGenerator; // The following two ratios mark the limit indentation (normalized by the radius) for releasing a particle // and for allowing a new one to be injected. admissible_indentation_ratio_for_release should be smaller // (more strict), since we want to make sure that the particle is taken far enough to avoid interferences diff --git a/applications/DEMApplication/custom_utilities/pre_utilities.h b/applications/DEMApplication/custom_utilities/pre_utilities.h index a1adfbc36e22..6de5297c3fa6 100644 --- a/applications/DEMApplication/custom_utilities/pre_utilities.h +++ b/applications/DEMApplication/custom_utilities/pre_utilities.h @@ -311,6 +311,7 @@ class PreUtilities outputfile << "POISSON_RATIO 0.20\n"; outputfile << "STATIC_FRICTION 0.5773502691896257\n"; outputfile << "DYNAMIC_FRICTION 0.5773502691896257\n"; + outputfile << "FRICTION_DECAY 500.0\n"; outputfile << "PARTICLE_COHESION 0.0\n"; outputfile << "COEFFICIENT_OF_RESTITUTION 0.2\n"; outputfile << "PARTICLE_MATERIAL 1\n"; diff --git a/applications/DEMApplication/custom_utilities/properties_proxies.cpp b/applications/DEMApplication/custom_utilities/properties_proxies.cpp index dc0d7c4a6814..4fa482a29877 100644 --- a/applications/DEMApplication/custom_utilities/properties_proxies.cpp +++ b/applications/DEMApplication/custom_utilities/properties_proxies.cpp @@ -46,6 +46,10 @@ namespace Kratos { double* PropertiesProxy::pGetTgOfDynamicFrictionAngle() { return mTgOfDynamicFrictionAngle; } void PropertiesProxy::SetTgOfDynamicFrictionAngleFromProperties(double* tg_of_dynamic_friction_angle) { mTgOfDynamicFrictionAngle = tg_of_dynamic_friction_angle;} + double PropertiesProxy::GetFrictionDecayCoefficient() { return *mFrictionDecayCoefficient; } + double* PropertiesProxy::pGetFrictionDecayCoefficient() { return mFrictionDecayCoefficient; } + void PropertiesProxy::SetFrictionDecayCoefficientFromProperties(double* friction_decay_coefficient) { mFrictionDecayCoefficient = friction_decay_coefficient;} + double PropertiesProxy::GetCoefficientOfRestitution() { return *mCoefficientOfRestitution; } double* PropertiesProxy::pGetCoefficientOfRestitution() { return mCoefficientOfRestitution; } void PropertiesProxy::SetCoefficientOfRestitutionFromProperties(double* coefficient_of_restitution) { mCoefficientOfRestitution = coefficient_of_restitution; } @@ -115,6 +119,7 @@ namespace Kratos { mRollingFrictionWithWalls = props.pGetRollingFrictionWithWalls(); mTgOfStaticFrictionAngle = props.pGetTgOfStaticFrictionAngle(); mTgOfDynamicFrictionAngle = props.pGetTgOfDynamicFrictionAngle(); + mFrictionDecayCoefficient = props.pGetFrictionDecayCoefficient(); mCoefficientOfRestitution = props.pGetCoefficientOfRestitution(); mLnOfRestitCoeff = props.pGetLnOfRestitCoeff(); mDensity = props.pGetDensity(); @@ -172,6 +177,9 @@ namespace Kratos { aux_pointer = &( props_it->GetValue(DYNAMIC_FRICTION) ); vector_of_proxies[properties_counter].SetTgOfDynamicFrictionAngleFromProperties(aux_pointer); + aux_pointer = &( props_it->GetValue(FRICTION_DECAY) ); + vector_of_proxies[properties_counter].SetFrictionDecayCoefficientFromProperties(aux_pointer); + aux_pointer = &( props_it->GetValue(COEFFICIENT_OF_RESTITUTION) ); vector_of_proxies[properties_counter].SetCoefficientOfRestitutionFromProperties(aux_pointer); diff --git a/applications/DEMApplication/custom_utilities/properties_proxies.h b/applications/DEMApplication/custom_utilities/properties_proxies.h index c05dc58015ef..6d0d160debfc 100644 --- a/applications/DEMApplication/custom_utilities/properties_proxies.h +++ b/applications/DEMApplication/custom_utilities/properties_proxies.h @@ -55,6 +55,10 @@ namespace Kratos { double* pGetTgOfDynamicFrictionAngle(); void SetTgOfDynamicFrictionAngleFromProperties(double* tg_of_dynamic_friction_angle); + double GetFrictionDecayCoefficient(); + double* pGetFrictionDecayCoefficient(); + void SetFrictionDecayCoefficientFromProperties(double* tg_of_dynamic_friction_angle); + double GetCoefficientOfRestitution(); double* pGetCoefficientOfRestitution(); void SetCoefficientOfRestitutionFromProperties(double* coefficient_of_restitution); @@ -126,6 +130,7 @@ namespace Kratos { double* mRollingFrictionWithWalls; double* mTgOfStaticFrictionAngle; double* mTgOfDynamicFrictionAngle; + double* mFrictionDecayCoefficient; double* mCoefficientOfRestitution; double* mLnOfRestitCoeff; double* mDensity; diff --git a/applications/DEMApplication/custom_utilities/rigid_face_geometrical_object_configure.h b/applications/DEMApplication/custom_utilities/rigid_face_geometrical_object_configure.h index f13b98ccb4e3..07303d43efd1 100644 --- a/applications/DEMApplication/custom_utilities/rigid_face_geometrical_object_configure.h +++ b/applications/DEMApplication/custom_utilities/rigid_face_geometrical_object_configure.h @@ -266,9 +266,10 @@ class RigidFaceGeometricalObjectConfigure SphericParticle* p_particle = static_cast(&*rObj_2); const double Radius = p_particle->GetSearchRadius(); - int facet_size = FE_Geom.WorkingSpaceDimension(); + const int facet_size = FE_Geom.size(); - if (facet_size==2) { + if (facet_size==1) return GeometryFunctions::FastVertexCheck(FE_Geom[0].Coordinates(),DE_Geom[0].Coordinates(), Radius); + else if (facet_size==2) { return FastIntersection2D(DE_Geom, FE_Geom, Radius);//, NewContactType); } else { @@ -281,9 +282,10 @@ class RigidFaceGeometricalObjectConfigure const GeometryType& DE_Geom = rObj_1->GetGeometry(); const GeometryType& FE_Geom = rObj_2->GetGeometry(); - int facet_size = FE_Geom.WorkingSpaceDimension(); + const int facet_size = FE_Geom.size(); - if (facet_size==2) { + if (facet_size==1) return GeometryFunctions::FastVertexCheck(FE_Geom[0].Coordinates(),DE_Geom[0].Coordinates(), Radius); + else if (facet_size==2) { return FastIntersection2D(DE_Geom, FE_Geom, Radius);//, NewContactType); } else { @@ -294,9 +296,10 @@ class RigidFaceGeometricalObjectConfigure //Copy of the Intersection function accessible with geometry static inline bool FastIntersection(const GeometryType& DE_Geom, const GeometryType& FE_Geom, const double& Radius) { //rObj_1 is sphere, rObj_2 is FE - int facet_size = FE_Geom.WorkingSpaceDimension(); + int facet_size = FE_Geom.size(); - if (facet_size==2) { + if (facet_size==1) return GeometryFunctions::FastVertexCheck(FE_Geom[0].Coordinates(),DE_Geom[0].Coordinates(), Radius); + else if (facet_size==2) { return FastIntersection2D(DE_Geom, FE_Geom, Radius);//, NewContactType); } else { diff --git a/applications/DEMApplication/python_scripts/DEM_analysis_stage.py b/applications/DEMApplication/python_scripts/DEM_analysis_stage.py index 5c1a82c3131a..4a6dc5722aa9 100644 --- a/applications/DEMApplication/python_scripts/DEM_analysis_stage.py +++ b/applications/DEMApplication/python_scripts/DEM_analysis_stage.py @@ -110,7 +110,6 @@ def __init__(self, model, DEM_parameters): self.p_count = self.p_frequency #self._solver = self._GetSolver() - self.SetDt() self.SetFinalTime() self.AddVariables() super().__init__(model, self.DEM_parameters) @@ -147,28 +146,15 @@ def SetAnalyticParticleWatcher(self): # is this being used? TODO self.particle_watcher_analyser = analytic_data_procedures.ParticleWatcherAnalyzer(analytic_particle_watcher=self.particle_watcher, path=self.main_path) - def SetAnalyticFaceWatcher(self): - from KratosMultiphysics.DEMApplication.analytic_tools import analytic_data_procedures - self.FaceAnalyzerClass = analytic_data_procedures.FaceWatcherAnalyzer - self.face_watcher_dict = dict() - self.face_watcher_analysers = dict() - for sub_part in self.rigid_face_model_part.SubModelParts: - if sub_part[IS_GHOST] == True: - name = sub_part.Name - self.face_watcher_dict[sub_part.Name] = AnalyticFaceWatcher(sub_part) - self.face_watcher_analysers[sub_part.Name] = analytic_data_procedures.FaceWatcherAnalyzer(name=name, analytic_face_watcher=self.face_watcher_dict[sub_part.Name], path=self.main_path) + self.FaceAnalyzerClass = analytic_data_procedures.FaceAnalyzerClass(self.rigid_face_model_part.SubModelParts, self.main_path) def MakeAnalyticsMeasurements(self): - for face_watcher in self.face_watcher_dict.values(): - face_watcher.MakeMeasurements() + self.FaceAnalyzerClass.MakeAnalyticsMeasurements() def SetFinalTime(self): self.end_time = self.DEM_parameters["FinalTime"].GetDouble() - def SetDt(self): - self._GetSolver().dt = self.DEM_parameters["MaxTimeStep"].GetDouble() - def SetProcedures(self): return DEM_procedures.Procedures(self.DEM_parameters) @@ -311,6 +297,7 @@ def Initialize(self): super().Initialize() + self.seed = self.DEM_parameters["seed"].GetInt() #Constructing a model part for the DEM inlet. It contains the DEM elements to be released during the simulation #Initializing the DEM solver must be done before creating the DEM Inlet, because the Inlet configures itself according to some options of the DEM model part self.SetInlet() @@ -463,13 +450,9 @@ def ConvertClusterFileNamesFromRelativePathToAbsolutePath(self): submp[CLUSTER_FILE_NAME] = os.path.join(self.main_path, cluster_file_name) def RunAnalytics(self, time, is_time_to_print=True): - for sp in (sp for sp in self.rigid_face_model_part.SubModelParts if sp[IS_GHOST]): - self.MakeAnalyticsMeasurements() - if is_time_to_print: - self.FaceAnalyzerClass.CreateNewFile() - for sp in (sp for sp in self.rigid_face_model_part.SubModelParts if sp[IS_GHOST]): - self.face_watcher_analysers[sp.Name].UpdateDataFiles(time) - self.FaceAnalyzerClass.RemoveOldFile() + self.MakeAnalyticsMeasurements() + if is_time_to_print: + self.FaceAnalyzerClass.MakeAnalyticsPipeLine(time) def IsTimeToPrintPostProcess(self): return self.do_print_results_option and self.DEM_parameters["OutputTimeStep"].GetDouble() - (self.time - self.time_old_print) < 1e-2 * self._GetSolver().dt @@ -486,7 +469,7 @@ def SolverSolve(self): def SetInlet(self): if self.DEM_parameters["dem_inlet_option"].GetBool(): #Constructing the inlet and initializing it (must be done AFTER the self.spheres_model_part Initialize) - self.DEM_inlet = DEM_Inlet(self.dem_inlet_model_part) + self.DEM_inlet = DEM_Inlet(self.dem_inlet_model_part, self.seed) self.DEM_inlet.InitializeDEM_Inlet(self.spheres_model_part, self.creator_destructor, self._GetSolver().continuum_type) def SetInitialNodalValues(self): diff --git a/applications/DEMApplication/python_scripts/DEM_material_test_script.py b/applications/DEMApplication/python_scripts/DEM_material_test_script.py index 37a0ee07c6a3..001a5158a0a6 100644 --- a/applications/DEMApplication/python_scripts/DEM_material_test_script.py +++ b/applications/DEMApplication/python_scripts/DEM_material_test_script.py @@ -424,6 +424,7 @@ def PrintChart(self): self.chart.write( " DENSI = " + (str(self.spheres_model_part.GetProperties()[1][PARTICLE_DENSITY]).rjust(3))+" Kg/m3 "+'\n') self.chart.write( " STAFRC = " + (str(self.spheres_model_part.GetProperties()[1][STATIC_FRICTION]).rjust(3))+" "+'\n') self.chart.write( " DYNFRC = " + (str(self.spheres_model_part.GetProperties()[1][DYNAMIC_FRICTION]).rjust(3))+" " +'\n') + self.chart.write( " FRCDEC = " + (str(self.spheres_model_part.GetProperties()[1][FRICTION_DECAY]).rjust(3))+" " +'\n') self.chart.write( " YOUNG = " + (str(self.spheres_model_part.GetProperties()[1][YOUNG_MODULUS]/1e9).rjust(3))+" GPa"+" " +'\n') self.chart.write( " POISS = " + (str(self.spheres_model_part.GetProperties()[1][POISSON_RATIO]).rjust(3))+" " +'\n') self.chart.write( " FTS = " + (str(self.spheres_model_part.GetProperties()[1][CONTACT_SIGMA_MIN]).rjust(3))+" Pa " +'\n') diff --git a/applications/DEMApplication/python_scripts/DEM_procedures.py b/applications/DEMApplication/python_scripts/DEM_procedures.py index e07d3bd1dd3f..fe89f126b988 100644 --- a/applications/DEMApplication/python_scripts/DEM_procedures.py +++ b/applications/DEMApplication/python_scripts/DEM_procedures.py @@ -372,7 +372,7 @@ def SetTranslationalScheme(self): elif self.DEM_parameters["TranslationalIntegrationScheme"].GetString() == 'Velocity_Verlet': translational_scheme = VelocityVerletScheme() else: - self.KratosPrintWarning('Error: selected translational integration scheme not defined. Please select a different scheme') + KratosPrintWarning('Error: selected translational integration scheme not defined. Please select a different scheme') sys.exit("\nExecution was aborted.\n") return translational_scheme @@ -391,7 +391,7 @@ def SetRotationalScheme(self): elif self.DEM_parameters["RotationalIntegrationScheme"].GetString() == 'Quaternion_Integration': rotational_scheme = QuaternionIntegrationScheme() else: - self.KratosPrintWarning('Error: selected rotational integration scheme not defined. Please select a different scheme') + KratosPrintWarning('Error: selected rotational integration scheme not defined. Please select a different scheme') sys.exit("\nExecution was aborted.\n") return rotational_scheme @@ -830,14 +830,14 @@ def CheckVariableType(self, var, expected_type, msg): # TODO is this actually if actual_type is int and expected_type is float: return if actual_type is not expected_type: - self.KratosPrintWarning( + KratosPrintWarning( "**************************************************************************") - self.KratosPrintWarning( + KratosPrintWarning( "ERROR: Input parameter of wrong type in file 'DEM_explicit_solver_var.py'.") a = str(expected_type) b = str(var) - self.KratosPrintWarning("The type expected was " + a + " but " + b + " was read.") - self.KratosPrintWarning( + KratosPrintWarning("The type expected was " + a + " but " + b + " was read.") + KratosPrintWarning( "**************************************************************************") sys.exit() @@ -976,6 +976,7 @@ def UpdateTimeInModelParts(self, all_model_parts, time, dt, step, is_time_to_pri @classmethod def UpdateTimeInOneModelPart(self, model_part, time, dt, step, is_time_to_print=False): + KratosPrintWarning('This method is deprecated, please use the new one from the sphere strategy.') model_part.ProcessInfo[TIME] = time model_part.ProcessInfo[DELTA_TIME] = dt model_part.ProcessInfo[TIME_STEPS] = step diff --git a/applications/DEMApplication/python_scripts/analytic_tools/analytic_data_procedures.py b/applications/DEMApplication/python_scripts/analytic_tools/analytic_data_procedures.py index 98c585f1fc13..8416244192c4 100644 --- a/applications/DEMApplication/python_scripts/analytic_tools/analytic_data_procedures.py +++ b/applications/DEMApplication/python_scripts/analytic_tools/analytic_data_procedures.py @@ -1,4 +1,7 @@ import os +import numpy as np +from KratosMultiphysics import * +from KratosMultiphysics.DEMApplication import * class ParticleWatcherAnalyzer: def __init__(self, analytic_particle_watcher, path, do_clear_data = True): @@ -13,54 +16,18 @@ def SetNodalMaxFaceImpactVelocities(self, analytic_model_part): class FaceWatcherAnalyzer: - def __init__(self, name, analytic_face_watcher, path, do_clear_data = True): + def __init__(self, name, analytic_face_watcher): self.face_watcher = analytic_face_watcher self.face_watcher_name = name - self.do_clear_data = do_clear_data # the following objects are useful if data is chunked into several databases - self.times_data_base_names = [] - self.n_particles_data_base_names = [] - self.mass_data_base_names = [] + self.inlet = None self.n_particles_accumulated = 0 self.mass_accumulated = 0.0 - self.inlet = None - - self.folder_path = path - self.file_path = path + '/flux_data_new.hdf5' - self.old_file_path = self.file_path.replace('_new.hdf5', '.hdf5') - - FaceWatcherAnalyzer.file_path = self.file_path - FaceWatcherAnalyzer.file_path_old =self.old_file_path - FaceWatcherAnalyzer.RemoveFiles() - - @staticmethod - def RemoveFiles(): - new_path = FaceWatcherAnalyzer.file_path - old_path = FaceWatcherAnalyzer.file_path_old - for path in (p for p in [new_path, old_path] if os.path.exists(p)): - os.remove(path) - - @staticmethod - def CreateNewFile(): - new_path = FaceWatcherAnalyzer.file_path - old_path = FaceWatcherAnalyzer.file_path_old - if os.path.exists(new_path): - os.rename(new_path, old_path) - - import h5py - h5py.File(new_path) - - @staticmethod - def RemoveOldFile(): - old_path = FaceWatcherAnalyzer.file_path_old - if os.path.exists(old_path): - os.remove(old_path) def MakeReading(self): times, number_flux, mass_flux, vel_nr_mass, vel_tg_mass = [], [], [], [], [] self.face_watcher.GetTotalFlux(times, number_flux, mass_flux, vel_nr_mass, vel_tg_mass) lists = [times, number_flux, mass_flux, vel_nr_mass, vel_tg_mass] - #times, number_flux, mass_flux, vel_nr_mass, vel_tg_mass = [np.array(l) for l in lists] times, number_flux, mass_flux, vel_nr_mass, vel_tg_mass = [l for l in lists] length = len(times) assert length == len(number_flux) == len(mass_flux) @@ -72,30 +39,6 @@ def MakeReading(self): return shape, times, number_flux, mass_flux, vel_nr_mass, vel_tg_mass - def GetTimes(self): - return self.GetJointData(self.times_data_base_names) - - def GetNumberOfParticlesFlux(self): - return self.GetJointData(self.n_particles_data_base_names) - - def GetMassFlux(self): - return self.GetJointData(self.mass_data_base_names) - - def GetJointData(self, data_base_names): - import numpy as np - import h5py - data_list = [] - - with h5py.File(self.file_path, 'r') as f: - if self.do_clear_data: # join all databases - for name in data_base_names: - data_list.append(f['/' + name].value) - joint_list = np.concatenate(data_list, axis = 0) - else: # get the latest - joint_list = f['/' + data_base_names[-1]].value - - return joint_list - def CalculateAccumulatedVectors(self, length, number_flux, mass_flux): acc_number_flux = self.CalculateAccumulated(original_list = number_flux, old_accumulated = self.n_particles_accumulated) acc_mass_flux = self.CalculateAccumulated(original_list = mass_flux, old_accumulated = self.mass_accumulated) @@ -103,82 +46,175 @@ def CalculateAccumulatedVectors(self, length, number_flux, mass_flux): return acc_number_flux, acc_mass_flux def CalculateAccumulated(self, original_list, old_accumulated = 0): - import numpy as np new_accumulated = np.cumsum(np.array(original_list)) + old_accumulated return new_accumulated - def OldFileExists(self): - return os.path.exists(self.old_file_path) - - def UpdateDataFiles(self, time): + def UpdateData(self, time): shape, time, n_particles, mass, vel_nr_mass = self.MakeReading()[:-1] # initial with 1 for each surface, should be one for each condition in each surface total_mass = sum(mass) - #total_mass = np.sum(mass) if total_mass: avg_vel_nr = vel_nr_mass / total_mass # sum (normal vel * particle_mass) / total mass flux of that timestep - #avg_vel_tg = vel_tg_mass / total_mass else: - #avg_vel_nr = np.zeros(mass.size) avg_vel_nr = [0.] * len(mass) - #avg_vel_tg = np.zeros(mass.size) - name_n_particles = 'n_accum' - name_mass = 'm_accum' - name_avg_vel_nr = 'mass_avg_normal_vel' + return shape, time, n_particles, mass, avg_vel_nr - # how to create subgrouped datasets with variable name: - # group2 = f.create_group('group2/subfolder') - # group2.create_dataset('data',data=d) + def MakeInletMassPlot(self): + self.MakeInletReading() + + def SetInlet(self, inlet): + self.inlet = inlet + + def UpdateVariables(self, n_particles_old, n_mass_old): + self.n_particles_accumulated = n_particles_old + self.mass_accumulated = n_mass_old + + def ClearData(self): + self.face_watcher.ClearData() + +class FaceAnalyzerClass: + def __init__(self, model_part, main_path, do_clear_data = True): + self.model_part = model_part + self.main_path = main_path + self.face_watcher_dict = dict() + self.face_watcher_analysers = dict() + self.do_clear_data = do_clear_data + self.times_data_base_names = [] + self.n_particles_data_base_names = [] + self.mass_data_base_names = [] + self.new_path = self.main_path + '/flux_data_new.hdf5' + self.old_path = self.new_path.replace('_new.hdf5', '.hdf5') + self.name_n_particles = 'n_accum' + self.name_mass = 'm_accum' + self.name_avg_vel_nr = 'mass_avg_normal_vel' - def CreateDataSets(f, current_shape): - surface_data = f.require_group(self.face_watcher_name) - surface_data.attrs['Surface Identifier'] = self.face_watcher_name + for sub_part in self.model_part: + if sub_part[IS_GHOST] == True: + self.face_watcher_dict[sub_part.Name] = AnalyticFaceWatcher(sub_part) + self.face_watcher_analysers[sub_part.Name] = FaceWatcherAnalyzer(name=sub_part.Name, analytic_face_watcher=self.face_watcher_dict[sub_part.Name]) - #time_db = surface_data.require_dataset('time', shape = current_shape, dtype = np.float64) - #n_particles_db = surface_data.require_dataset(name_n_particles, shape = current_shape, dtype = np.int64) - #mass_db = surface_data.require_dataset(name_mass, shape = current_shape, dtype = np.float64) - #avg_vel_nr_db = surface_data.require_dataset(name_avg_vel_nr, shape = current_shape, dtype = np.float64) + self.RemoveFiles() - time_db = surface_data.require_dataset('time', shape = current_shape, dtype = float) - n_particles_db = surface_data.require_dataset(name_n_particles, shape = current_shape, dtype = int) - mass_db = surface_data.require_dataset(name_mass, shape = current_shape, dtype = float) - avg_vel_nr_db = surface_data.require_dataset(name_avg_vel_nr, shape = current_shape, dtype = float) - return time_db, n_particles_db, mass_db, avg_vel_nr_db + def MakeAnalyticsMeasurements(self): + for face_watcher in self.face_watcher_dict.values(): + face_watcher.MakeMeasurements() + def MakeAnalyticsPipeLine(self, time): + self.CreateNewFile() + self.UpdateDataBases(time) + self.RemoveOldFile() + + def CreateNewFile(self): import h5py - if self.OldFileExists(): + if os.path.exists(self.new_path): + os.rename(self.new_path, self.old_path) - with h5py.File(self.file_path) as f, h5py.File(self.old_file_path, 'r') as f_old: - shape_old = f_old['/' + self.face_watcher_name + '/time'].shape - current_shape = (shape_old[0] + shape[0], ) - time_db, n_particles_db, mass_db, avg_vel_nr_db = CreateDataSets(f, current_shape) + h5py.File(self.new_path, 'a') - time_db[:shape_old[0]] = f_old['/' + self.face_watcher_name + '/time'][:] - time_db[shape_old[0]:] = time[:] - n_particles_db[:shape_old[0]] = f_old['/' + self.face_watcher_name + '/' + name_n_particles][:] - n_particles_db[shape_old[0]:] = n_particles[:] - mass_db[:shape_old[0]] = f_old['/' + self.face_watcher_name + '/' + name_mass][:] - mass_db[shape_old[0]:] = mass[:] - avg_vel_nr_db[:shape_old[0]] = f_old['/' + self.face_watcher_name + '/' + name_avg_vel_nr][:] - avg_vel_nr_db[shape_old[0]:] = avg_vel_nr[:] + def RemoveOldFile(self): + if os.path.exists(self.old_path): + os.remove(self.old_path) + + def RemoveFiles(self): + for path in (p for p in [self.new_path, self.old_path] if os.path.exists(p)): + os.remove(path) + def UpdateDataBases(self, time): + if self.OldFileExists(): + self.UpdateDataFile(time) else: - with h5py.File(self.file_path) as f: - time_db, n_particles_db, mass_db, avg_vel_nr_db = CreateDataSets(f, shape) - time_db[:] = time[:] - n_particles_db[:] = n_particles[:] - mass_db[:] = mass[:] - avg_vel_nr_db[:] = avg_vel_nr[:] + self.CreateDataFile(time) + + def UpdateDataFile(self, time): + + # how to create subgrouped datasets with variable name: + # group2 = f.create_group('group2/subfolder') + # group2.create_dataset('data',data=d) + import h5py + with h5py.File(self.new_path, 'a') as f, h5py.File(self.old_path, 'r') as f_old: + for sub_part in self.model_part: + if sub_part[IS_GHOST]: + shape, time, n_particles, mass, avg_vel_nr = self.face_watcher_analysers[sub_part.Name].UpdateData(time) + shape_old = f_old['/' + sub_part.Name + '/time'].shape + current_shape = (shape_old[0] + shape[0], ) + time_db, n_particles_db, mass_db, avg_vel_nr_db = self.CreateDataSets(f, current_shape, sub_part.Name) + + time_db[:shape_old[0]] = f_old['/' + sub_part.Name + '/time'][:] + time_db[shape_old[0]:] = time[:] + n_particles_db[:shape_old[0]] = f_old['/' + sub_part.Name + '/' + self.name_n_particles][:] + n_particles_db[shape_old[0]:] = n_particles[:] + mass_db[:shape_old[0]] = f_old['/' + sub_part.Name + '/' + self.name_mass][:] + mass_db[shape_old[0]:] = mass[:] + avg_vel_nr_db[:shape_old[0]] = f_old['/' + sub_part.Name + '/' + self.name_avg_vel_nr][:] + avg_vel_nr_db[shape_old[0]:] = avg_vel_nr[:] + if self.do_clear_data: + if len(n_particles): + self.face_watcher_analysers[sub_part.Name].UpdateVariables(n_particles[-1], mass[-1]) + self.face_watcher_analysers[sub_part.Name].ClearData() # how to extract data from h5 subgrouped datasets: #input_data = h5py.File('Cemib_P660_SpreadPattern.dat.hdf5','r') #x_h5 = input_data.get('/patch/X') #x = np.array(x_h5) - if self.do_clear_data: - if len(n_particles): - self.n_particles_accumulated = n_particles[-1] - self.mass_accumulated = mass[-1] - self.face_watcher.ClearData() + def CreateDataFile(self, time): + + # how to create subgrouped datasets with variable name: + # group2 = f.create_group('group2/subfolder') + # group2.create_dataset('data',data=d) + import h5py + with h5py.File(self.new_path, 'a') as f: + for sub_part in self.model_part: + if sub_part[IS_GHOST]: + shape, time, n_particles, mass, avg_vel_nr = self.face_watcher_analysers[sub_part.Name].UpdateData(time) + time_db, n_particles_db, mass_db, avg_vel_nr_db = self.CreateDataSets(f, shape, sub_part.Name) + time_db[:] = time[:] + n_particles_db[:] = n_particles[:] + mass_db[:] = mass[:] + avg_vel_nr_db[:] = avg_vel_nr[:] + if self.do_clear_data: + if len(n_particles): + self.face_watcher_analysers[sub_part.Name].UpdateVariables(n_particles[-1], mass[-1]) + self.face_watcher_analysers[sub_part.Name].ClearData() + + #input_data = h5py.File('Cemib_P660_SpreadPattern.dat.hdf5','r') + #x_h5 = input_data.get('/patch/X') + #x = np.array(x_h5) + + def CreateDataSets(self, f, current_shape, sp_name): + surface_data = f.require_group(sp_name) + surface_data.attrs['Surface Identifier'] = sp_name + + time_db = surface_data.require_dataset('time', shape = current_shape, dtype = np.float64) + n_particles_db = surface_data.require_dataset(self.name_n_particles, shape = current_shape, dtype = np.int64) + mass_db = surface_data.require_dataset(self.name_mass, shape = current_shape, dtype = np.float64) + avg_vel_nr_db = surface_data.require_dataset(self.name_avg_vel_nr, shape = current_shape, dtype = np.float64) + + return time_db, n_particles_db, mass_db, avg_vel_nr_db + + def OldFileExists(self): + return os.path.exists(self.old_path) + + def GetJointData(self, data_base_names): + data_list = [] + import h5py + with h5py.File(self.new_path, 'r') as f: + if self.do_clear_data: # join all databases + for name in data_base_names: + data_list.append(f['/' + name].value) + joint_list = np.concatenate(data_list, axis = 0) + else: # get the latest + joint_list = f['/' + data_base_names[-1]].value + + return joint_list + + def GetTimes(self): + return self.GetJointData(self.times_data_base_names) + + def GetNumberOfParticlesFlux(self): + return self.GetJointData(self.n_particles_data_base_names) + + def GetMassFlux(self): + return self.GetJointData(self.mass_data_base_names) def MakeTotalFluxPlot(self): import matplotlib.pyplot as plt @@ -189,7 +225,7 @@ def MakeTotalFluxPlot(self): plt.xlabel('time') plt.ylabel('accumulated mass throughput') plt.plot(times, mass_flux) - plt.savefig(self.folder_path + '/mass_throughput.pdf', bbox_inches='tight') + plt.savefig(self.main_path + '/mass_throughput.pdf', bbox_inches='tight') def MakeFluxOfNumberOfParticlesPlot(self): import matplotlib.pyplot as plt @@ -200,12 +236,6 @@ def MakeFluxOfNumberOfParticlesPlot(self): plt.xlabel('time') plt.ylabel('accumulated number of particles through surface') plt.plot(times, flux) - plt.savefig(self.folder_path + '/throughput.svg') + plt.savefig(self.main_path + '/throughput.svg') plt.clf() ''' - - def MakeInletMassPlot(self): - self.MakeInletReading() - - def SetInlet(self, inlet): - self.inlet = inlet diff --git a/applications/DEMApplication/python_scripts/dem_default_input_parameters.py b/applications/DEMApplication/python_scripts/dem_default_input_parameters.py index beb23a80011c..18ceca760573 100644 --- a/applications/DEMApplication/python_scripts/dem_default_input_parameters.py +++ b/applications/DEMApplication/python_scripts/dem_default_input_parameters.py @@ -20,6 +20,7 @@ def GetDefaultInputParameters(): "BoundingBoxMinY" : -10.0, "BoundingBoxMinZ" : -10.0, "dem_inlet_option" : true, + "seed" : 42, "GravityX" : 0.0, "GravityY" : 0.0, "GravityZ" : -9.81, diff --git a/applications/DEMApplication/python_scripts/processes/apply_forces_and_moments_process.py b/applications/DEMApplication/python_scripts/processes/apply_forces_and_moments_process.py new file mode 100644 index 000000000000..69aa90eda919 --- /dev/null +++ b/applications/DEMApplication/python_scripts/processes/apply_forces_and_moments_process.py @@ -0,0 +1,38 @@ +import KratosMultiphysics + +# Import applications +import KratosMultiphysics.DEMApplication as DEM + +# Other imports + +def Factory(settings, Model): + if(type(settings) != KratosMultiphysics.Parameters): + raise Exception("expected input shall be a Parameters object, encapsulating a json string") + + process_settings = settings["Parameters"] + + folder_settings = KratosMultiphysics.Parameters("""{ + "help" : "This process applies loads over the particles in a certain submodelpart, for a certain time interval", + "mesh_id" : 0, + "model_part_name" : "please_specify_model_part_name", + "force_settings" : { + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "moment_settings" : { + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "interval" : [0.0, 1e30] + }""" ) + + process_settings.AddMissingParameters(folder_settings) + + if process_settings.Has("model_part_name"): + computing_model_part = Model[process_settings["model_part_name"].GetString()] + else: # using default name + computing_model_part = Model["DEM"] + + process_settings.RemoveValue("help") + + return DEM.ApplyForcesAndMomentsProcess(computing_model_part, process_settings) diff --git a/applications/DEMApplication/python_scripts/processes/apply_forces_and_moments_to_walls_process.py b/applications/DEMApplication/python_scripts/processes/apply_forces_and_moments_to_walls_process.py new file mode 100644 index 000000000000..28a825eadf6e --- /dev/null +++ b/applications/DEMApplication/python_scripts/processes/apply_forces_and_moments_to_walls_process.py @@ -0,0 +1,38 @@ +import KratosMultiphysics + +# Import applications +import KratosMultiphysics.DEMApplication as DEM + +# Other imports + +def Factory(settings, Model): + if(type(settings) != KratosMultiphysics.Parameters): + raise Exception("expected input shall be a Parameters object, encapsulating a json string") + + process_settings = settings["Parameters"] + + folder_settings = KratosMultiphysics.Parameters("""{ + "help" : "This process applies loads over the rigid walls in a certain submodelpart, for a certain time interval", + "mesh_id" : 0, + "model_part_name" : "please_specify_model_part_name", + "force_settings" : { + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "moment_settings" : { + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "interval" : [0.0, 1e30] + }""" ) + + process_settings.AddMissingParameters(folder_settings) + + if process_settings.Has("model_part_name"): + computing_model_part = Model[process_settings["model_part_name"].GetString()] + else: # using default name + computing_model_part = Model["DEM_FEM_boundary"] + + process_settings.RemoveValue("help") + + return DEM.ApplyForcesAndMomentsToWallsProcess(computing_model_part, process_settings) diff --git a/applications/DEMApplication/python_scripts/processes/apply_kinematic_constraints_process.py b/applications/DEMApplication/python_scripts/processes/apply_kinematic_constraints_process.py index 7f1439687bed..349c51c86946 100644 --- a/applications/DEMApplication/python_scripts/processes/apply_kinematic_constraints_process.py +++ b/applications/DEMApplication/python_scripts/processes/apply_kinematic_constraints_process.py @@ -1,77 +1,42 @@ -# Importing the Kratos Library import KratosMultiphysics + +# Import applications import KratosMultiphysics.DEMApplication as DEM +# Other imports + def Factory(settings, Model): - if not isinstance(settings, KratosMultiphysics.Parameters): + if(type(settings) != KratosMultiphysics.Parameters): raise Exception("expected input shall be a Parameters object, encapsulating a json string") - return ApplyKinematicConstraintsProcess(Model, settings["Parameters"]) - -## All the processes python should be derived from "Process" -class ApplyKinematicConstraintsProcess(KratosMultiphysics.Process): - """This process assigns a given value (vector) to the nodes belonging a certain submodelpart - - Only the member variables listed below should be accessed directly. - - Public member variables: - Model -- the container of the different model parts. - settings -- Kratos parameters containing solver settings. - """ - - def __init__(self, Model, settings): - """ The default constructor of the class - - Keyword arguments: - self -- It signifies an instance of a class. - Model -- the container of the different model parts. - settings -- Kratos parameters containing solver settings. - """ - - KratosMultiphysics.Process.__init__(self) - - default_settings = KratosMultiphysics.Parameters(""" - { - "help" : "This process applies constraints to the particles in a certain submodelpart, for a certain time interval", - "mesh_id" : 0, - "model_part_name" : "please_specify_model_part_name", - "velocity_constraints_settings" : { - "constrained" : [true,true,true], - "value" : [10.0, "3*t", "x+y"] - }, - "angular_velocity_constraints_settings" : { - "constrained" : [true,true,true], - "value" : [10.0, "3*t", "x+y"] - }, - "interval" : [0.0, 1e30] - } - """ - ) - #example of admissible values for "value" : [10.0, "3*t", "x+y"] - - ## Trick to ensure that if someone sets constrained as a single bool, it is transformed to a vector - if settings["velocity_constraints_settings"].Has("constrained"): - if settings["velocity_constraints_settings"]["constrained"].IsBool(): - is_fixed = settings["velocity_constraints_settings"]["constrained"].GetBool() - settings["velocity_constraints_settings"]["constrained"] = default_settings["velocity_constraints_settings"]["constrained"] - for i in range(3): - settings["velocity_constraints_settings"]["constrained"][i].SetBool(is_fixed) - - if settings["angular_velocity_constraints_settings"].Has("constrained"): - if settings["angular_velocity_constraints_settings"]["constrained"].IsBool(): - is_fixed = settings["angular_velocity_constraints_settings"]["constrained"].GetBool() - settings["angular_velocity_constraints_settings"]["constrained"] = default_settings["angular_velocity_constraints_settings"]["constrained"] - for i in range(3): - settings["angular_velocity_constraints_settings"]["constrained"][i].SetBool(is_fixed) - - settings.ValidateAndAssignDefaults(default_settings) - - self.model_part = Model[settings["model_part_name"].GetString()] - self.cplusplus_version_of_this_process = DEM.ApplyKinematicConstraintsProcess(self.model_part, settings) - - - def ExecuteInitializeSolutionStep(self): - self.cplusplus_version_of_this_process.ExecuteInitializeSolutionStep() - - def ExecuteFinalizeSolutionStep(self): - self.cplusplus_version_of_this_process.ExecuteFinalizeSolutionStep() + process_settings = settings["Parameters"] + + folder_settings = KratosMultiphysics.Parameters(""" + { + "help" : "This process applies constraints to the particles in a certain submodelpart, for a certain time interval", + "mesh_id" : 0, + "model_part_name" : "please_specify_model_part_name", + "velocity_constraints_settings" : { + "constrained" : [true,true,true], + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "angular_velocity_constraints_settings" : { + "constrained" : [true,true,true], + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "interval" : [0.0, 1e30] + } + """) + + process_settings.AddMissingParameters(folder_settings) + + if process_settings.Has("model_part_name"): + computing_model_part = Model[process_settings["model_part_name"].GetString()] + else: # using default name + computing_model_part = Model["DEM"] + + process_settings.RemoveValue("help") + + return DEM.ApplyKinematicConstraintsProcess(computing_model_part, process_settings) diff --git a/applications/DEMApplication/python_scripts/processes/apply_kinematic_constraints_to_walls_process.py b/applications/DEMApplication/python_scripts/processes/apply_kinematic_constraints_to_walls_process.py new file mode 100644 index 000000000000..a570eb86ce48 --- /dev/null +++ b/applications/DEMApplication/python_scripts/processes/apply_kinematic_constraints_to_walls_process.py @@ -0,0 +1,42 @@ +import KratosMultiphysics + +# Import applications +import KratosMultiphysics.DEMApplication as DEM + +# Other imports + +def Factory(settings, Model): + if(type(settings) != KratosMultiphysics.Parameters): + raise Exception("expected input shall be a Parameters object, encapsulating a json string") + + process_settings = settings["Parameters"] + + folder_settings = KratosMultiphysics.Parameters(""" + { + "help" : "This process applies constraints to the particles in a certain submodelpart, for a certain time interval", + "mesh_id" : 0, + "model_part_name" : "please_specify_model_part_name", + "velocity_constraints_settings" : { + "constrained" : [true,true,true], + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "angular_velocity_constraints_settings" : { + "constrained" : [true,true,true], + "value" : [10.0, "3*t", "x+y"], + "table" : [0, 0, 0] + }, + "interval" : [0.0, 1e30] + } + """) + + process_settings.AddMissingParameters(folder_settings) + + if process_settings.Has("model_part_name"): + computing_model_part = Model[process_settings["model_part_name"].GetString()] + else: # using default name + computing_model_part = Model["DEM"] + + process_settings.RemoveValue("help") + + return DEM.ApplyKinematicConstraintsToWallsProcess(computing_model_part, process_settings) diff --git a/applications/DEMApplication/python_scripts/sphere_strategy.py b/applications/DEMApplication/python_scripts/sphere_strategy.py index 9b4df8e9db8b..fb7259ba06f7 100644 --- a/applications/DEMApplication/python_scripts/sphere_strategy.py +++ b/applications/DEMApplication/python_scripts/sphere_strategy.py @@ -110,7 +110,7 @@ def __init__(self, all_model_parts, creator_destructor, dem_fem_search, DEM_para # TIME RELATED PARAMETERS - self.delta_time = DEM_parameters["MaxTimeStep"].GetDouble() + self.dt = DEM_parameters["MaxTimeStep"].GetDouble() self.max_delta_time = DEM_parameters["MaxTimeStep"].GetDouble() self.end_time = DEM_parameters["FinalTime"].GetDouble() @@ -268,7 +268,7 @@ def SetVariablesAndOptions(self): self.spheres_model_part.ProcessInfo.SetValue(PRINT_EXPORT_ID, self.print_export_id) # TIME RELATED PARAMETERS - self.spheres_model_part.ProcessInfo.SetValue(DELTA_TIME, self.delta_time) + self.spheres_model_part.ProcessInfo.SetValue(DELTA_TIME, self.dt) #-----os.chdir('..') # check functionality @@ -400,16 +400,22 @@ def _UpdateTimeInModelParts(self, time, is_time_to_print = False): dem_inlet_model_part = self.all_model_parts.Get("DEMInletPart") rigid_face_model_part = self.all_model_parts.Get("RigidFacePart") - self._UpdateTimeInOneModelPart(spheres_model_part, time, is_time_to_print) - self._UpdateTimeInOneModelPart(cluster_model_part, time, is_time_to_print) - self._UpdateTimeInOneModelPart(dem_inlet_model_part, time, is_time_to_print) - self._UpdateTimeInOneModelPart(rigid_face_model_part, time, is_time_to_print) + self._UpdateTimeInOneModelPart(spheres_model_part, time, self.dt, is_time_to_print) + self._UpdateTimeInOneModelPart(cluster_model_part, time, self.dt, is_time_to_print) + self._UpdateTimeInOneModelPart(dem_inlet_model_part, time, self.dt, is_time_to_print) + self._UpdateTimeInOneModelPart(rigid_face_model_part, time, self.dt, is_time_to_print) - def _UpdateTimeInOneModelPart(self, model_part, time, is_time_to_print = False): - model_part.ProcessInfo[TIME] = time - model_part.ProcessInfo[DELTA_TIME] = self.dt - model_part.ProcessInfo[TIME_STEPS] += 1 - model_part.ProcessInfo[IS_TIME_TO_PRINT] = is_time_to_print + @classmethod + def _UpdateTimeInOneModelPart(self, model_part, time, dt, is_time_to_print = False): + ''' This method is redirected to its cpp version with improved speed. + It also has been updated to classmethod and args so it can be called from external App + ''' + + AuxiliaryUtilities().UpdateTimeInOneModelPart(model_part, time, dt, is_time_to_print) + # model_part.ProcessInfo[TIME] = time + # model_part.ProcessInfo[DELTA_TIME] = dt + # model_part.ProcessInfo[TIME_STEPS] += 1 + # model_part.ProcessInfo[IS_TIME_TO_PRINT] = is_time_to_print def FinalizeSolutionStep(self): (self.cplusplus_strategy).FinalizeSolutionStep() @@ -683,11 +689,15 @@ def ModifyProperties(self, properties, param = 0): if properties.Has(FRICTION): self.Procedures.KratosPrintWarning("-------------------------------------------------") self.Procedures.KratosPrintWarning(" WARNING: Property FRICTION is deprecated since April 6th, 2020, ") - self.Procedures.KratosPrintWarning(" replace with STATIC_FRICTION and DYNAMIC_FRICTION") + self.Procedures.KratosPrintWarning(" replace with STATIC_FRICTION, DYNAMIC_FRICTION and FRICTION_DECAY") self.Procedures.KratosPrintWarning(" Automatic replacement is done now.") self.Procedures.KratosPrintWarning("-------------------------------------------------") properties[STATIC_FRICTION] = properties[FRICTION] properties[DYNAMIC_FRICTION] = properties[FRICTION] + properties[FRICTION_DECAY] = 500.0 + + if not properties.Has(FRICTION_DECAY): + properties[FRICTION_DECAY] = 500.0 translational_scheme, error_status, summary_mssg = self.GetTranslationalScheme(translational_scheme_name) diff --git a/applications/DEMApplication/python_scripts/verlet_continuum_sphere_strategy.py b/applications/DEMApplication/python_scripts/verlet_continuum_sphere_strategy.py index 980a65075031..a02c37fac3fb 100644 --- a/applications/DEMApplication/python_scripts/verlet_continuum_sphere_strategy.py +++ b/applications/DEMApplication/python_scripts/verlet_continuum_sphere_strategy.py @@ -49,7 +49,7 @@ def CreateCPlusPlusStrategy(self): self.SetOneOrZeroInProcessInfoAccordingToBoolValue(self.spheres_model_part, ROLLING_FRICTION_OPTION, self.rolling_friction_option) # TIME RELATED PARAMETERS - self.model_part.ProcessInfo.SetValue(DELTA_TIME, self.delta_time) + self.model_part.ProcessInfo.SetValue(DELTA_TIME, self.dt) for properties in self.model_part.Properties: self.ModifyProperties(properties) diff --git a/applications/DEMApplication/tests/DEM2D_control_module_tests_files/ProjectParametersDEM.json b/applications/DEMApplication/tests/DEM2D_control_module_tests_files/ProjectParametersDEM.json index 9e3626aaa2bf..086d7cf26464 100644 --- a/applications/DEMApplication/tests/DEM2D_control_module_tests_files/ProjectParametersDEM.json +++ b/applications/DEMApplication/tests/DEM2D_control_module_tests_files/ProjectParametersDEM.json @@ -58,9 +58,11 @@ "MeasuringSurface" : 0.00806117 }, "processes" : { - "constraints_process_list" : [] + "constraints_process_list" : [], + "loads_process_list" : [], + "list_other_processes" : [] }, - "ImposeZStrainIn2DOption" : true, + "ImposeZStrainIn2DOption" : true, "ZStrainValue" : "0.0", "ImposeZStrainIn2DWithControlModule" : true, "OutputTimeStep" : 1.0e-6, diff --git a/applications/DEMApplication/tests/forces_and_moments_tests_files/ProjectParametersDEM.json b/applications/DEMApplication/tests/forces_and_moments_tests_files/ProjectParametersDEM.json new file mode 100644 index 000000000000..4b4dc1791ac5 --- /dev/null +++ b/applications/DEMApplication/tests/forces_and_moments_tests_files/ProjectParametersDEM.json @@ -0,0 +1,125 @@ +{ + "Dimension" : 3, + "PeriodicDomainOption" : false, + "BoundingBoxOption" : false, + "AutomaticBoundingBoxOption" : false, + "BoundingBoxEnlargementFactor" : 1.1, + "BoundingBoxStartTime" : 0.0, + "BoundingBoxStopTime" : 1000.0, + "BoundingBoxMaxX" : 10, + "BoundingBoxMaxY" : 10, + "BoundingBoxMaxZ" : 10, + "BoundingBoxMinX" : -10, + "BoundingBoxMinY" : -10, + "BoundingBoxMinZ" : -10, + "dem_inlet_option" : false, + "GravityX" : 0.0, + "GravityY" : -9.81, + "GravityZ" : 0.0, + "RotationOption" : true, + "CleanIndentationsOption" : false, + "solver_settings" : { + "RemoveBallsInitiallyTouchingWalls" : false, + "strategy" : "sphere_strategy" + }, + "processes" : { + "constraints_process_list" : [], + "loads_process_list" : [{ + "python_module" : "processes.apply_forces_and_moments_process", + "kratos_module" : "KratosMultiphysics.DEMApplication", + "Parameters" : { + "model_part_name" : "SpheresPart.Ball1", + "force_settings" : { + "value" : [100.0, "30.0*t", "2000.0*(x+y)"], + "table" : [null, null, null] + }, + "moment_settings" : { + "value" : [-50.0, "15.0*(x+z)", "600.0*t"], + "table" : [null, null, null] + }, + "interval" : [0.0, 0.2] + } + },{ + "python_module" : "processes.apply_forces_and_moments_process", + "kratos_module" : "KratosMultiphysics.DEMApplication", + "Parameters" : { + "model_part_name" : "SpheresPart.Ball2", + "force_settings" : { + "value" : [null, null, null], + "table" : [1, 2, 3] + }, + "moment_settings" : { + "value" : [null, null, null], + "table" : [4, 5, 6] + }, + "interval" : [0.0, 1.0e30] + } + },{ + "python_module" : "processes.apply_forces_and_moments_to_walls_process", + "kratos_module" : "KratosMultiphysics.DEMApplication", + "Parameters" : { + "model_part_name" : "RigidFacePart.Cube1", + "force_settings" : { + "value" : ["-90.0*t", 300.0, "250.0*(x+y)"], + "table" : [null, null, null] + }, + "moment_settings" : { + "value" : ["(y**2+z)", "-700.0*t", 800.0], + "table" : [null, null, null] + }, + "interval" : [0.2, 0.4] + } + },{ + "python_module" : "processes.apply_forces_and_moments_to_walls_process", + "kratos_module" : "KratosMultiphysics.DEMApplication", + "Parameters" : { + "model_part_name" : "RigidFacePart.Cube2", + "force_settings" : { + "value" : [null, null, null], + "table" : [7, 8, 9] + }, + "moment_settings" : { + "value" : [null, null, null], + "table" : [10, 11, 12] + }, + "interval" : [0.0, 1.0e30] + } + }], + "list_other_processes" : [] + }, + "VirtualMassCoefficient" : 1.0, + "RollingFrictionOption" : false, + "GlobalDamping" : 0.0, + "ContactMeshOption" : false, + "OutputFileType" : "Binary", + "Multifile" : "multiple_files", + "ElementType" : "SphericPartDEMElement3D", + "TranslationalIntegrationScheme" : "Symplectic_Euler", + "RotationalIntegrationScheme" : "Direct_Integration", + "MaxTimeStep" : 0.0002, + "FinalTime" : 0.4, + "NeighbourSearchFrequency" : 50, + "GraphExportFreq" : 0.001, + "VelTrapGraphExportFreq" : 0.001, + "OutputTimeStep" : 0.01, + "PostBoundingBox" : false, + "PostLocalContactForce" : false, + "PostDisplacement" : false, + "PostRadius" : false, + "PostVelocity" : true, + "PostAngularVelocity" : true, + "PostElasticForces" : false, + "PostContactForces" : false, + "PostRigidElementForces" : false, + "PostStressStrainOption" : false, + "PostTangentialElasticForces" : false, + "PostTotalForces" : false, + "PostAppliedForces" : true, + "PostPressure" : false, + "PostShearStress" : false, + "PostNonDimensionalVolumeWear" : false, + "PostParticleMoment" : false, + "PostEulerAngles" : false, + "PostRollingResistanceMoment" : false, + "problem_name" : "forces_and_moments_process" +} diff --git a/applications/DEMApplication/tests/forces_and_moments_tests_files/forces_and_moments_processDEM.mdpa b/applications/DEMApplication/tests/forces_and_moments_tests_files/forces_and_moments_processDEM.mdpa new file mode 100644 index 000000000000..aecb98e0fbb4 --- /dev/null +++ b/applications/DEMApplication/tests/forces_and_moments_tests_files/forces_and_moments_processDEM.mdpa @@ -0,0 +1,94 @@ +Begin ModelPartData +// VARIABLE_NAME value +End ModelPartData + +Begin Properties 1 + DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Hertz_viscous_Coulomb + PARTICLE_DENSITY 2500.0 + YOUNG_MODULUS 1000000.0 + POISSON_RATIO 0.20 + STATIC_FRICTION 0.009138776996010534 + DYNAMIC_FRICTION 0.009138776996010534 + FRICTION_DECAY 500.0 + COEFFICIENT_OF_RESTITUTION 0.2 + PARTICLE_MATERIAL 1 + ROLLING_FRICTION 0.01 + ROLLING_FRICTION_WITH_WALLS 0.01 + PARTICLE_SPHERICITY 1.0 + DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw +End Properties + +Begin Table 1 TIME VALUE + 0.0 0.0 + 0.1 10000.0 +End Table + +Begin Table 2 TIME VALUE + 0.0 0.0 + 0.1 300.0 +End Table + +Begin Table 3 TIME VALUE + 0.0 0.0 + 0.1 6000.0 +End Table + +Begin Table 4 TIME VALUE + 0.0 0.0 + 0.1 50000.0 +End Table + +Begin Table 5 TIME VALUE + 0.0 0.0 + 0.1 600.0 +End Table + +Begin Table 6 TIME VALUE + 0.0 0.0 + 0.1 7000.0 +End Table + +Begin Nodes + 1 0.0 0.0 2.0 + 2 10.0 0.0 2.0 +End Nodes + +Begin Elements SphericParticle3D + 1 1 1 + 2 1 2 +End Elements + +Begin NodalData RADIUS + 1 0 1.0 + 2 0 1.0 +End NodalData + +Begin SubModelPart Ball1 + Begin SubModelPartNodes + 1 + End SubModelPartNodes + Begin SubModelPartElements + 1 + End SubModelPartElements + Begin SubModelPartConditions + End SubModelPartConditions +End SubModelPart + +Begin SubModelPart Ball2 + Begin SubModelPartNodes + 2 + End SubModelPartNodes + Begin SubModelPartElements + 2 + End SubModelPartElements + Begin SubModelPartConditions + End SubModelPartConditions + Begin SubModelPartTables + 1 + 2 + 3 + 4 + 5 + 6 + End SubModelPartTables +End SubModelPart diff --git a/applications/DEMApplication/tests/forces_and_moments_tests_files/forces_and_moments_processDEM_FEM_boundary.mdpa b/applications/DEMApplication/tests/forces_and_moments_tests_files/forces_and_moments_processDEM_FEM_boundary.mdpa new file mode 100644 index 000000000000..1eeeee13c029 --- /dev/null +++ b/applications/DEMApplication/tests/forces_and_moments_tests_files/forces_and_moments_processDEM_FEM_boundary.mdpa @@ -0,0 +1,172 @@ +Begin ModelPartData +// VARIABLE_NAME value +End ModelPartData + +Begin Properties 2 + STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 + FRICTION_DECAY 500.0 + WALL_COHESION 0.0 + COMPUTE_WEAR 0 + SEVERITY_OF_WEAR 0.001 + IMPACT_WEAR_SEVERITY 0.001 + BRINELL_HARDNESS 200.0 + YOUNG_MODULUS 1e+20 + POISSON_RATIO 0.25 +End Properties + +Begin Table 7 TIME VALUE + 0.0 0.0 + 0.1 10000.0 +End Table + +Begin Table 8 TIME VALUE + 0.0 0.0 + 0.1 300.0 +End Table + +Begin Table 9 TIME VALUE + 0.0 0.0 + 0.1 6000.0 +End Table + +Begin Table 10 TIME VALUE + 0.0 0.0 + 0.1 50000.0 +End Table + +Begin Table 11 TIME VALUE + 0.0 0.0 + 0.1 600.0 +End Table + +Begin Table 12 TIME VALUE + 0.0 0.0 + 0.1 7000.0 +End Table + +Begin Nodes + 3 1.0000000000 1.0000000000 -1.0000000000 + 4 1.0000000000 -1.0000000000 -1.0000000000 + 5 -1.0000000000 1.0000000000 -1.0000000000 + 6 1.0000000000 1.0000000000 1.0000000000 + 7 -1.0000000000 -1.0000000000 -1.0000000000 + 8 1.0000000000 -1.0000000000 1.0000000000 + 9 -1.0000000000 1.0000000000 1.0000000000 + 10 -1.0000000000 -1.0000000000 1.0000000000 + 13 11.0000000000 1.0000000000 -1.0000000000 + 14 11.0000000000 -1.0000000000 -1.0000000000 + 15 9.0000000000 1.0000000000 -1.0000000000 + 16 11.0000000000 1.0000000000 1.0000000000 + 17 9.0000000000 -1.0000000000 -1.0000000000 + 18 11.0000000000 -1.0000000000 1.0000000000 + 19 9.0000000000 1.0000000000 1.0000000000 + 20 9.0000000000 -1.0000000000 1.0000000000 +End Nodes + +Begin Conditions RigidFace3D3N// GUI group identifier: Cube + 3 2 4 3 7 + 4 2 3 5 7 + 5 2 4 8 7 + 6 2 8 10 7 + 7 2 3 6 4 + 8 2 6 8 4 + 9 2 5 9 3 + 10 2 9 6 3 + 11 2 7 10 5 + 12 2 10 9 5 + 13 2 8 6 10 + 14 2 6 9 10 + 15 2 14 13 17 + 16 2 13 15 17 + 17 2 14 18 17 + 18 2 18 20 17 + 19 2 13 16 14 + 20 2 16 18 14 + 21 2 15 19 13 + 22 2 19 16 13 + 23 2 17 20 15 + 24 2 20 19 15 + 25 2 18 16 20 + 26 2 16 19 20 +End Conditions + +Begin SubModelPart Cube1 + Begin SubModelPartData + RIGID_BODY_MASS 1.0 + RIGID_BODY_CENTER_OF_MASS [3] (0.0,0.0,0.0) + RIGID_BODY_INERTIAS [3] (0.66667,0.66667,0.66667) + FREE_BODY_MOTION 1 + IDENTIFIER Cube + FORCE_INTEGRATION_GROUP 0 + End SubModelPartData + Begin SubModelPartNodes + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + End SubModelPartNodes + Begin SubModelPartConditions + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + End SubModelPartConditions + Begin SubModelPartTables + End SubModelPartTables +End SubModelPart + +Begin SubModelPart Cube2 + Begin SubModelPartData + RIGID_BODY_MASS 1.0 + RIGID_BODY_CENTER_OF_MASS [3] (10.0,0.0,0.0) + RIGID_BODY_INERTIAS [3] (0.66667,0.66667,0.66667) + FREE_BODY_MOTION 1 + IDENTIFIER Cube + FORCE_INTEGRATION_GROUP 0 + End SubModelPartData + Begin SubModelPartNodes + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + End SubModelPartNodes + Begin SubModelPartConditions + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + End SubModelPartConditions + Begin SubModelPartTables + 7 + 8 + 9 + 10 + 11 + 12 + End SubModelPartTables +End SubModelPart diff --git a/applications/DEMApplication/tests/friction_decay_tests_files/ProjectParametersDEM.json b/applications/DEMApplication/tests/friction_decay_tests_files/ProjectParametersDEM.json new file mode 100644 index 000000000000..99d7e1439a03 --- /dev/null +++ b/applications/DEMApplication/tests/friction_decay_tests_files/ProjectParametersDEM.json @@ -0,0 +1,85 @@ +{ +"Dimension" : 3, +"PeriodicDomainOption" : false, +"BoundingBoxOption" : true, +"AutomaticBoundingBoxOption" : false, +"BoundingBoxEnlargementFactor" : 1.0, +"BoundingBoxStartTime" : 0.0, +"BoundingBoxStopTime" : 1000.0, +"BoundingBoxMaxX" : 10, +"BoundingBoxMaxY" : 10, +"BoundingBoxMaxZ" : 10, +"BoundingBoxMinX" : -10, +"BoundingBoxMinY" : -10, +"BoundingBoxMinZ" : -10, + +"dem_inlet_option" : false, +"GravityX" : 0.0, +"GravityY" : 0.0, +"GravityZ" : -9.81, + +"EnergyCalculationOption" : false, +"VelocityTrapOption" : false, +"RotationOption" : false, +"CleanIndentationsOption" : false, +"solver_settings" : { + "strategy" : "sphere_strategy", + "RemoveBallsInitiallyTouchingWalls" : false +}, + +"RemoveBallsInEmbeddedOption" : true, + +"DeltaOption" : "Absolute", +"SearchTolerance" : 0.0, +"AmplifiedSearchRadiusExtension" : 0.0, +"ModelDataInfo" : false, +"VirtualMassCoefficient" : 1.0, +"RollingFrictionOption" : false, +"GlobalDamping" : 0.0, +"ContactMeshOption" : false, +"OutputFileType" : "Binary", +"Multifile" : "multiple_files", +"ElementType" : "SphericPartDEMElement3D", + +"TranslationalIntegrationScheme" : "Symplectic_Euler", +"RotationalIntegrationScheme" : "Direct_Integration", +"AutomaticTimestep" : false, +"DeltaTimeSafetyFactor" : 1.0, +"MaxTimeStep" : 1e-4, +"FinalTime" : 0.075, +"ControlTime" : 4.0, +"NeighbourSearchFrequency" : 50, + +"GraphExportFreq" : 1e-3, +"VelTrapGraphExportFreq" : 1e-3, +"OutputTimeStep" : 1e-2, +"PostBoundingBox" : false, +"PostDisplacement" : false, +"PostVelocity" : true, +"PostTotalForces" : true, +"PostRigidElementForces" : true, +"PostRadius" : false, +"PostAngularVelocity" : false, +"PostParticleMoment" : false, +"PostEulerAngles" : false, +"PostRollingResistanceMoment" : false, +"PostCharacteristicLength" : false, + +"PostElasticForces" : false, +"PostContactForces" : true, +"PostTangentialElasticForces" : false, +"PostShearStress" : false, +"PostPressure" : false, + +"PostNonDimensionalVolumeWear" : false, +"PostNodalArea" : false, + +"PostLocalContactForce" : false, +"PostRHS" : false, +"PostDampForces" : false, +"PostAppliedForces" : false, +"PostGroupId" : false, +"PostExportId" : false, + +"problem_name" : "friction_decay_test" +} diff --git a/applications/DEMApplication/tests/friction_decay_tests_files/friction_decay_testDEM.mdpa b/applications/DEMApplication/tests/friction_decay_tests_files/friction_decay_testDEM.mdpa new file mode 100644 index 000000000000..7e1bfdf5606d --- /dev/null +++ b/applications/DEMApplication/tests/friction_decay_tests_files/friction_decay_testDEM.mdpa @@ -0,0 +1,104 @@ +Begin ModelPartData +// VARIABLE_NAME value +End ModelPartData + +Begin Properties 1 +PARTICLE_DENSITY 2500.0 +YOUNG_MODULUS 1.0e6 +POISSON_RATIO 0.20 +STATIC_FRICTION 0.6 +DYNAMIC_FRICTION 0.4 +FRICTION_DECAY 500.0 +PARTICLE_COHESION 0.0 +COEFFICIENT_OF_RESTITUTION 0.2 +PARTICLE_MATERIAL 1 +ROLLING_FRICTION 0.01 +ROLLING_FRICTION_WITH_WALLS 0.01 +DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Hertz_viscous_Coulomb +DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw +End Properties + +Begin Properties 2 +PARTICLE_DENSITY 2500.0 +YOUNG_MODULUS 1.0e6 +POISSON_RATIO 0.20 +STATIC_FRICTION 0.6 +DYNAMIC_FRICTION 0.4 +FRICTION_DECAY 5.0 +PARTICLE_COHESION 0.0 +COEFFICIENT_OF_RESTITUTION 0.2 +PARTICLE_MATERIAL 2 +ROLLING_FRICTION 0.01 +ROLLING_FRICTION_WITH_WALLS 0.01 +DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Hertz_viscous_Coulomb +DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw +End Properties + +Begin Nodes // GUI group identifier: DEMElem0 celemid SphericPartDEMElement3D +1 0.00 0.00 0.249 +2 0.00 1.00 0.249 +3 1.00 0.00 0.249 +4 1.00 1.00 0.249 +5 2.00 0.00 0.249 +6 2.00 1.00 0.249 +End Nodes + +Begin Elements SphericParticle3D // GUI group identifier: DEMElem1 +1 1 1 +2 2 2 +3 1 3 +4 2 4 +5 1 5 +6 2 6 +End Elements + +Begin NodalData RADIUS // GUI group identifier: DEMElem0 Elementid SphericPartDEMElement3D +1 0 0.25 +2 0 0.25 +3 0 0.25 +4 0 0.25 +5 0 0.25 +6 0 0.25 +End NodalData + +Begin SubModelPart 1 // GUI DEM-VelocityBC - DEM-VelocityBC - group identifier: fixed_DEM + Begin SubModelPartData // DEM-VelocityBC. Group name: fixed_DEM + IMPOSED_VELOCITY_X_VALUE 0.01 + IMPOSED_VELOCITY_Y_VALUE 0.0 + IMPOSED_VELOCITY_Z_VALUE 0.0 + VELOCITY_START_TIME 0.0 + VELOCITY_STOP_TIME 100.0 + End SubModelPartData + Begin SubModelPartNodes + 1 + 2 + End SubModelPartNodes +End SubModelPart + +Begin SubModelPart 2 // GUI DEM-VelocityBC - DEM-VelocityBC - group identifier: fixed_DEM + Begin SubModelPartData // DEM-VelocityBC. Group name: fixed_DEM + IMPOSED_VELOCITY_X_VALUE 0.1 + IMPOSED_VELOCITY_Y_VALUE 0.0 + IMPOSED_VELOCITY_Z_VALUE 0.0 + VELOCITY_START_TIME 0.0 + VELOCITY_STOP_TIME 100.0 + End SubModelPartData + Begin SubModelPartNodes + 3 + 4 + End SubModelPartNodes +End SubModelPart + +Begin SubModelPart 3 // GUI DEM-VelocityBC - DEM-VelocityBC - group identifier: fixed_DEM + Begin SubModelPartData // DEM-VelocityBC. Group name: fixed_DEM + IMPOSED_VELOCITY_X_VALUE 1.0 + IMPOSED_VELOCITY_Y_VALUE 0.0 + IMPOSED_VELOCITY_Z_VALUE 0.0 + VELOCITY_START_TIME 0.0 + VELOCITY_STOP_TIME 100.0 + End SubModelPartData + Begin SubModelPartNodes + 5 + 6 + End SubModelPartNodes +End SubModelPart diff --git a/applications/DEMApplication/tests/friction_decay_tests_files/friction_decay_testDEM_FEM_boundary.mdpa b/applications/DEMApplication/tests/friction_decay_tests_files/friction_decay_testDEM_FEM_boundary.mdpa new file mode 100644 index 000000000000..ee6bb9efaa47 --- /dev/null +++ b/applications/DEMApplication/tests/friction_decay_tests_files/friction_decay_testDEM_FEM_boundary.mdpa @@ -0,0 +1,84 @@ +Begin ModelPartData +// VARIABLE_NAME value +End ModelPartData + +Begin Properties 3 +STATIC_FRICTION 0.6 +DYNAMIC_FRICTION 0.4 +FRICTION_DECAY 500.0 +WALL_COHESION 0.0 +COMPUTE_WEAR 0 +SEVERITY_OF_WEAR 0.001 +IMPACT_WEAR_SEVERITY 0.001 +BRINELL_HARDNESS 200.0 +YOUNG_MODULUS 1e6 +POISSON_RATIO 0.20 +End Properties + +Begin Properties 4 +STATIC_FRICTION 0.6 +DYNAMIC_FRICTION 0.4 +FRICTION_DECAY 5.0 +WALL_COHESION 0.0 +COMPUTE_WEAR 0 +SEVERITY_OF_WEAR 0.001 +IMPACT_WEAR_SEVERITY 0.001 +BRINELL_HARDNESS 200.0 +YOUNG_MODULUS 1e6 +POISSON_RATIO 0.20 +End Properties + +Begin Nodes // GUI DEM-FEM-Wall group identifier: DEM-wall1 +3 -0.25 -0.25 0.00 +4 -0.25 0.25 0.00 +5 2.25 0.25 0.00 +6 2.25 -0.25 0.00 +7 -0.25 0.75 0.00 +8 -0.25 1.25 0.00 +9 2.25 1.25 0.00 +10 2.25 0.75 0.00 +End Nodes + +Begin Conditions RigidFace3D4N // GUI DEM-FEM-Wall group identifier: DEM-wall1 +3 3 3 4 5 6 +End Conditions + +Begin Conditions RigidFace3D4N // GUI DEM-FEM-Wall group identifier: DEM-wall2 +4 4 7 8 9 10 +End Conditions + +Begin SubModelPart 3 // DEM-FEM-Wall. Group name: DEM-wall1 + Begin SubModelPartData // DEM-FEM-Wall. Group name: DEM-wall1 + PROPERTIES_ID 3 + IDENTIFIER DEM-wall1 + End SubModelPartData + Begin SubModelPartNodes + 3 + 4 + 5 + 6 + End SubModelPartNodes + Begin SubModelPartConditions + 3 + End SubModelPartConditions + Begin SubModelPartTables + End SubModelPartTables +End SubModelPart + +Begin SubModelPart 4 // DEM-FEM-Wall. Group name: DEM-wall2 + Begin SubModelPartData // DEM-FEM-Wall. Group name: DEM-wall2 + PROPERTIES_ID 4 + IDENTIFIER DEM-wall2 + End SubModelPartData + Begin SubModelPartNodes + 7 + 8 + 9 + 10 + End SubModelPartNodes + Begin SubModelPartConditions + 4 + End SubModelPartConditions + Begin SubModelPartTables + End SubModelPartTables +End SubModelPart diff --git a/applications/DEMApplication/tests/kinematic_constraints_tests_files/ProjectParametersDEM.json b/applications/DEMApplication/tests/kinematic_constraints_tests_files/ProjectParametersDEM.json index 240458f66775..89868db074ab 100644 --- a/applications/DEMApplication/tests/kinematic_constraints_tests_files/ProjectParametersDEM.json +++ b/applications/DEMApplication/tests/kinematic_constraints_tests_files/ProjectParametersDEM.json @@ -30,11 +30,13 @@ "model_part_name" : "SpheresPart.Ball1", "velocity_constraints_settings" : { "constrained" : [true,true,true], - "value" : [0.0, 0.0, 0.0] + "value" : [0.0, 0.0, 0.0], + "table" : [null, null, null] }, "angular_velocity_constraints_settings" : { "constrained" : [true,true,true], - "value" : [0.0, 0.0, 0.0] + "value" : [0.0, 0.0, 0.0], + "table" : [null, null, null] }, "interval" : [0.0, 0.2] } @@ -45,11 +47,13 @@ "model_part_name" : "SpheresPart.Ball2", "velocity_constraints_settings" : { "constrained" : [true,true,true], - "value" : ["-10.0*t", 0.0, 0.0] + "value" : ["-10.0*t", 0.0, 0.0], + "table" : [null, null, null] }, "angular_velocity_constraints_settings" : { "constrained" : [true,true,true], - "value" : [0.0, 0.0, 0.0] + "value" : [0.0, 0.0, 0.0], + "table" : [null, null, null] }, "interval" : [0.2, 0.4] } @@ -60,11 +64,13 @@ "model_part_name" : "SpheresPart.Ball3", "velocity_constraints_settings" : { "constrained" : [true,true,true], - "value" : [-5.0, 0.0, 0.0] + "value" : [-5.0, 0.0, 0.0], + "table" : [null, null, null] }, "angular_velocity_constraints_settings" : { "constrained" : [true,true,true], - "value" : [0.0, 0.0, -10.0] + "value" : [0.0, 0.0, -10.0], + "table" : [null, null, null] }, "interval" : [0.0, 0.1] } @@ -75,14 +81,67 @@ "model_part_name" : "SpheresPart.Ball4", "velocity_constraints_settings" : { "constrained" : [false, false, true], - "value" : [10000.0, 3000.0, 0.0] + "value" : [10000.0, 3000.0, 0.0], + "table" : [null, null, null] }, "angular_velocity_constraints_settings" : { "constrained" : [false, false, false], - "value" : [1000.0, "3000.0*t", "x+y+1000.0"] + "value" : [1000.0, "3000.0*t", "x+y+1000.0"], + "table" : [null, null, null] }, "interval" : [0.0, 1e30] } + },{ + "python_module" : "processes.apply_kinematic_constraints_process", + "kratos_module" : "KratosMultiphysics.DEMApplication", + "Parameters" : { + "model_part_name" : "SpheresPart.Ball5", + "velocity_constraints_settings" : { + "constrained" : [false, false, true], + "value" : [null, null, null], + "table" : [1, 2, 3] + }, + "angular_velocity_constraints_settings" : { + "constrained" : [false, false, false], + "value" : [null, null, null], + "table" : [4, 5, 6] + }, + "interval" : [0.0, 1e30] + } + },{ + "python_module" : "processes.apply_kinematic_constraints_to_walls_process", + "kratos_module" : "KratosMultiphysics.DEMApplication", + "Parameters" : { + "model_part_name" : "RigidFacePart.Cube1", + "velocity_constraints_settings" : { + "constrained" : [true, true, true], + "value" : ["-0.5*t", 0.6, "(x+y)"], + "table" : [null, null, null] + }, + "angular_velocity_constraints_settings" : { + "constrained" : [true, true, true], + "value" : ["(y**2+z)", "-2.0*t", 1.0], + "table" : [null, null, null] + }, + "interval" : [0.0, 1.0e30] + } + },{ + "python_module" : "processes.apply_kinematic_constraints_to_walls_process", + "kratos_module" : "KratosMultiphysics.DEMApplication", + "Parameters" : { + "model_part_name" : "RigidFacePart.Cube2", + "velocity_constraints_settings" : { + "constrained" : [true, true, true], + "value" : [null, null, null], + "table" : [7, 8, 9] + }, + "angular_velocity_constraints_settings" : { + "constrained" : [true, true, true], + "value" : [null, null, null], + "table" : [10, 11, 12] + }, + "interval" : [0.0, 1.0e30] + } }], "loads_process_list" : [], "list_other_processes" : [] diff --git a/applications/DEMApplication/tests/kinematic_constraints_tests_files/processesDEM.mdpa b/applications/DEMApplication/tests/kinematic_constraints_tests_files/processesDEM.mdpa index 574f4e0110c9..29ce5e7ea665 100644 --- a/applications/DEMApplication/tests/kinematic_constraints_tests_files/processesDEM.mdpa +++ b/applications/DEMApplication/tests/kinematic_constraints_tests_files/processesDEM.mdpa @@ -9,6 +9,7 @@ Begin Properties 1 POISSON_RATIO 0.20 STATIC_FRICTION 0.009138776996010534 DYNAMIC_FRICTION 0.009138776996010534 + FRICTION_DECAY 500.0 COEFFICIENT_OF_RESTITUTION 0.2 PARTICLE_MATERIAL 1 ROLLING_FRICTION 0.01 @@ -17,6 +18,36 @@ Begin Properties 1 DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw End Properties +Begin Table 1 TIME VALUE + 0.0 0.0 + 1.0 10.0 +End Table + +Begin Table 2 TIME VALUE + 0.0 0.0 + 1.0 10.0 +End Table + +Begin Table 3 TIME VALUE + 0.0 0.0 + 1.0 10.0 +End Table + +Begin Table 4 TIME VALUE + 0.0 0.0 + 1.0 10.0 +End Table + +Begin Table 5 TIME VALUE + 0.0 0.0 + 1.0 10.0 +End Table + +Begin Table 6 TIME VALUE + 0.0 0.0 + 1.0 10.0 +End Table + Begin Nodes 1 7.0000000000 0.0000000000 0.0000000000 2 6.0000000000 0.0000000000 0.0000000000 @@ -84,6 +115,8 @@ Begin SubModelPart Ball1 End SubModelPartElements Begin SubModelPartConditions End SubModelPartConditions + Begin SubModelPartTables + End SubModelPartTables End SubModelPart Begin SubModelPart Ball2 Begin SubModelPartNodes @@ -94,6 +127,8 @@ Begin SubModelPart Ball2 End SubModelPartElements Begin SubModelPartConditions End SubModelPartConditions + Begin SubModelPartTables + End SubModelPartTables End SubModelPart Begin SubModelPart Ball3 Begin SubModelPartNodes @@ -104,6 +139,8 @@ Begin SubModelPart Ball3 End SubModelPartElements Begin SubModelPartConditions End SubModelPartConditions + Begin SubModelPartTables + End SubModelPartTables End SubModelPart Begin SubModelPart Ball4 Begin SubModelPartNodes @@ -114,4 +151,24 @@ Begin SubModelPart Ball4 End SubModelPartElements Begin SubModelPartConditions End SubModelPartConditions + Begin SubModelPartTables + End SubModelPartTables +End SubModelPart +Begin SubModelPart Ball5 + Begin SubModelPartNodes + 5 + End SubModelPartNodes + Begin SubModelPartElements + 5 + End SubModelPartElements + Begin SubModelPartConditions + End SubModelPartConditions + Begin SubModelPartTables + 1 + 2 + 3 + 4 + 5 + 6 + End SubModelPartTables End SubModelPart diff --git a/applications/DEMApplication/tests/kinematic_constraints_tests_files/processesDEM_FEM_boundary.mdpa b/applications/DEMApplication/tests/kinematic_constraints_tests_files/processesDEM_FEM_boundary.mdpa new file mode 100644 index 000000000000..b0132684da62 --- /dev/null +++ b/applications/DEMApplication/tests/kinematic_constraints_tests_files/processesDEM_FEM_boundary.mdpa @@ -0,0 +1,172 @@ +Begin ModelPartData +// VARIABLE_NAME value +End ModelPartData + +Begin Properties 2 + STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 + FRICTION_DECAY 500.0 + WALL_COHESION 0.0 + COMPUTE_WEAR 0 + SEVERITY_OF_WEAR 0.001 + IMPACT_WEAR_SEVERITY 0.001 + BRINELL_HARDNESS 200.0 + YOUNG_MODULUS 1e+20 + POISSON_RATIO 0.25 +End Properties + +Begin Table 7 TIME VALUE + 0.0 0.0 + 1.0 10.0 +End Table + +Begin Table 8 TIME VALUE + 0.0 0.0 + 1.0 3.0 +End Table + +Begin Table 9 TIME VALUE + 0.0 0.0 + 1.0 0.6 +End Table + +Begin Table 10 TIME VALUE + 0.0 0.0 + 1.0 0.75 +End Table + +Begin Table 11 TIME VALUE + 0.0 0.0 + 1.0 4.0 +End Table + +Begin Table 12 TIME VALUE + 0.0 0.0 + 1.0 9.0 +End Table + +Begin Nodes + 3 8.2500000000 0.2500000000 -0.2500000000 + 4 8.2500000000 -0.2500000000 -0.2500000000 + 5 7.7500000000 0.2500000000 -0.2500000000 + 6 8.2500000000 0.2500000000 0.2500000000 + 7 7.7500000000 -0.2500000000 -0.2500000000 + 8 8.2500000000 -0.2500000000 0.2500000000 + 9 7.7500000000 0.2500000000 0.2500000000 + 10 7.7500000000 -0.2500000000 0.2500000000 + 13 9.2500000000 0.2500000000 -0.2500000000 + 14 9.2500000000 -0.2500000000 -0.2500000000 + 15 8.7500000000 0.2500000000 -0.2500000000 + 16 9.2500000000 0.2500000000 0.2500000000 + 17 8.7500000000 -0.2500000000 -0.2500000000 + 18 9.2500000000 -0.2500000000 0.2500000000 + 19 8.7500000000 0.2500000000 0.2500000000 + 20 8.7500000000 -0.2500000000 0.2500000000 +End Nodes + +Begin Conditions RigidFace3D3N// GUI group identifier: Cube + 3 2 4 3 7 + 4 2 3 5 7 + 5 2 4 8 7 + 6 2 8 10 7 + 7 2 3 6 4 + 8 2 6 8 4 + 9 2 5 9 3 + 10 2 9 6 3 + 11 2 7 10 5 + 12 2 10 9 5 + 13 2 8 6 10 + 14 2 6 9 10 + 15 2 14 13 17 + 16 2 13 15 17 + 17 2 14 18 17 + 18 2 18 20 17 + 19 2 13 16 14 + 20 2 16 18 14 + 21 2 15 19 13 + 22 2 19 16 13 + 23 2 17 20 15 + 24 2 20 19 15 + 25 2 18 16 20 + 26 2 16 19 20 +End Conditions + +Begin SubModelPart Cube1 + Begin SubModelPartData + RIGID_BODY_MASS 1.0 + RIGID_BODY_CENTER_OF_MASS [3] (8.0,0.0,0.0) + RIGID_BODY_INERTIAS [3] (0.66667,0.66667,0.66667) + FREE_BODY_MOTION 1 + IDENTIFIER Cube + FORCE_INTEGRATION_GROUP 0 + End SubModelPartData + Begin SubModelPartNodes + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + End SubModelPartNodes + Begin SubModelPartConditions + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + End SubModelPartConditions + Begin SubModelPartTables + End SubModelPartTables +End SubModelPart + +Begin SubModelPart Cube2 + Begin SubModelPartData + RIGID_BODY_MASS 1.0 + RIGID_BODY_CENTER_OF_MASS [3] (9.0,0.0,0.0) + RIGID_BODY_INERTIAS [3] (0.66667,0.66667,0.66667) + FREE_BODY_MOTION 1 + IDENTIFIER Cube + FORCE_INTEGRATION_GROUP 0 + End SubModelPartData + Begin SubModelPartNodes + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + End SubModelPartNodes + Begin SubModelPartConditions + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + End SubModelPartConditions + Begin SubModelPartTables + 7 + 8 + 9 + 10 + 11 + 12 + End SubModelPartTables +End SubModelPart diff --git a/applications/DEMApplication/tests/test_DEMApplication.py b/applications/DEMApplication/tests/test_DEMApplication.py index 150bf415061d..182c9bad3858 100644 --- a/applications/DEMApplication/tests/test_DEMApplication.py +++ b/applications/DEMApplication/tests/test_DEMApplication.py @@ -18,6 +18,8 @@ import test_DEM_2D_inlet import test_DEM_2D_control_module import test_post_process +import test_friction_decay +import test_forces_and_moments def AssembleTestSuites(): @@ -57,6 +59,8 @@ def AssembleTestSuites(): smallSuite.addTest(test_DEM_3D_continuum.TestDEM3DContinuum("test_DEM3D_continuum")) smallSuite.addTest(test_DEM_2D_control_module.TestDEM2DControlModule("test_DEM2D_control_module")) smallSuite.addTest(test_post_process.TestPostProcess("test_gid_printing_many_results")) + smallSuite.addTest(test_friction_decay.TestFrictionDecay("test_Friction_Decay")) + smallSuite.addTest(test_forces_and_moments.TestExternalForcesAndMoments("test_ForcesAndMoments")) # Create a test suit with the selected tests plus all small tests nightSuite = suites['nightly'] diff --git a/applications/DEMApplication/tests/test_DEM_2D.py b/applications/DEMApplication/tests/test_DEM_2D.py index 987518b9b08b..9d2eaed80fdc 100644 --- a/applications/DEMApplication/tests/test_DEM_2D.py +++ b/applications/DEMApplication/tests/test_DEM_2D.py @@ -50,11 +50,11 @@ def test_DEM2D_1(self): model = Kratos.Model() auxiliary_functions_for_tests.CreateAndRunStageInSelectedNumberOfOpenMPThreads(DEM2DTestSolution, model, parameters_file_name, 1) - def tearDown(self): file_to_remove = os.path.join("DEM2D_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) - + file_to_remove = os.path.join("DEM2D_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_DEM_2D_contact.py b/applications/DEMApplication/tests/test_DEM_2D_contact.py index f14ab751c1ad..9f4e08e9df05 100644 --- a/applications/DEMApplication/tests/test_DEM_2D_contact.py +++ b/applications/DEMApplication/tests/test_DEM_2D_contact.py @@ -59,6 +59,8 @@ def test_DEM2D_contact(self): def tearDown(self): file_to_remove = os.path.join("DEM2D_contact_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("DEM2D_contact_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_DEM_2D_control_module.py b/applications/DEMApplication/tests/test_DEM_2D_control_module.py index d7b4f8e73157..12667c64bba8 100644 --- a/applications/DEMApplication/tests/test_DEM_2D_control_module.py +++ b/applications/DEMApplication/tests/test_DEM_2D_control_module.py @@ -80,6 +80,8 @@ def test_DEM2D_control_module(self): def tearDown(self): file_to_remove = os.path.join("DEM2D_control_module_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("DEM2D_control_module_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_DEM_2D_inlet.py b/applications/DEMApplication/tests/test_DEM_2D_inlet.py index 437dfd0331dc..f300fda93a4a 100644 --- a/applications/DEMApplication/tests/test_DEM_2D_inlet.py +++ b/applications/DEMApplication/tests/test_DEM_2D_inlet.py @@ -52,6 +52,8 @@ def test_DEM2D_inlet(self): def tearDown(self): file_to_remove = os.path.join("DEM2D_inlet_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("DEM2D_inlet_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_DEM_2D_restitution.py b/applications/DEMApplication/tests/test_DEM_2D_restitution.py index 18eea97ff36a..9c927b2236c8 100644 --- a/applications/DEMApplication/tests/test_DEM_2D_restitution.py +++ b/applications/DEMApplication/tests/test_DEM_2D_restitution.py @@ -150,10 +150,11 @@ def test_DEM2D_restitution_2(self): model = KratosMultiphysics.Model() auxiliary_functions_for_tests.CreateAndRunStageInSelectedNumberOfOpenMPThreads(DEM2D_RestitutionTestSolution_2, model, parameters_file_name, 1) - def tearDown(self): file_to_remove = os.path.join("DEM2D_restitution_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("DEM2D_restitution_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_DEM_3D_contact.py b/applications/DEMApplication/tests/test_DEM_3D_contact.py index 9fdf5e8084b0..c920655f133e 100644 --- a/applications/DEMApplication/tests/test_DEM_3D_contact.py +++ b/applications/DEMApplication/tests/test_DEM_3D_contact.py @@ -54,6 +54,8 @@ def test_DEM3D_contact(self): def tearDown(self): file_to_remove = os.path.join("DEM3D_contact_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("DEM3D_contact_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_DEM_3D_continuum.py b/applications/DEMApplication/tests/test_DEM_3D_continuum.py index 89a12c0f1faf..14de8de20f88 100644 --- a/applications/DEMApplication/tests/test_DEM_3D_continuum.py +++ b/applications/DEMApplication/tests/test_DEM_3D_continuum.py @@ -183,6 +183,8 @@ def test_DEM3D_continuum(self): def tearDown(self): file_to_remove = os.path.join("test_DEM_3D_continuum", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("test_DEM_3D_continuum", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_DEM_3D_restitution.py b/applications/DEMApplication/tests/test_DEM_3D_restitution.py index 4689b29296cd..3ca8095c9b21 100644 --- a/applications/DEMApplication/tests/test_DEM_3D_restitution.py +++ b/applications/DEMApplication/tests/test_DEM_3D_restitution.py @@ -157,10 +157,11 @@ def test_DEM3D_restitution_2(self): model = KratosMultiphysics.Model() auxiliary_functions_for_tests.CreateAndRunStageInSelectedNumberOfOpenMPThreads(DEM3D_RestitutionTestSolution_2, model, parameters_file_name, 1) - def tearDown(self): file_to_remove = os.path.join("DEM3D_restitution_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("DEM3D_restitution_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_analytics.py b/applications/DEMApplication/tests/test_analytics.py index a2a6d0f9c069..44498b5881a2 100644 --- a/applications/DEMApplication/tests/test_analytics.py +++ b/applications/DEMApplication/tests/test_analytics.py @@ -59,9 +59,8 @@ def RunAnalytics(self, time, is_time_to_print=True): self.MakeAnalyticsMeasurements() if is_time_to_print: self.FaceAnalyzerClass.CreateNewFile() - for sp in (sp for sp in self.rigid_face_model_part.SubModelParts if sp[DEM.IS_GHOST]): - self.face_watcher_analysers[sp.Name].UpdateDataFiles(time) - self.CheckTotalNumberOfCrossingParticles() + self.FaceAnalyzerClass.UpdateDataBases(time) + self.CheckTotalNumberOfCrossingParticles() self.FaceAnalyzerClass.RemoveOldFile() @@ -83,16 +82,15 @@ def GetProblemNameWithPath(self): return os.path.join(self.main_path, self.DEM_parameters["problem_name"].GetString()) def RunAnalytics(self, time, is_time_to_print=True): - self.MakeAnalyticsMeasurements() - if is_time_to_print: # or IsCountStep() - self.FaceAnalyzerClass.CreateNewFile() - for sp in (sp for sp in self.rigid_face_model_part.SubModelParts if sp[DEM.IS_GHOST]): - self.face_watcher_analysers[sp.Name].UpdateDataFiles(time) + self.MakeAnalyticsMeasurements() + if is_time_to_print: # or IsCountStep() + self.FaceAnalyzerClass.CreateNewFile() + self.FaceAnalyzerClass.UpdateDataBases(time) - if sp[Kratos.IDENTIFIER] == 'DEM-wall2': - self.CheckTotalNumberOfCrossingParticles() + if sp[Kratos.IDENTIFIER] == 'DEM-wall2': + self.CheckTotalNumberOfCrossingParticles() - self.FaceAnalyzerClass.RemoveOldFile() + self.FaceAnalyzerClass.RemoveOldFile() def CheckTotalNumberOfCrossingParticles(self): import h5py @@ -132,11 +130,11 @@ def test_Analytics_1(self): # model = Kratos.Model() # CreateAndRunStageInSelectedNumberOfOpenMPThreads(MultiGhostsTestSolution, model, parameters_file_name, 1) - def tearDown(self): file_to_remove = os.path.join("analytics_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) - + file_to_remove = os.path.join("analytics_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_forces_and_moments.py b/applications/DEMApplication/tests/test_forces_and_moments.py new file mode 100644 index 000000000000..e335661b5613 --- /dev/null +++ b/applications/DEMApplication/tests/test_forces_and_moments.py @@ -0,0 +1,106 @@ +import os +import KratosMultiphysics as Kratos +from KratosMultiphysics import Logger +Logger.GetDefaultOutput().SetSeverity(Logger.Severity.WARNING) +import KratosMultiphysics.KratosUnittest as KratosUnittest +import KratosMultiphysics.DEMApplication.DEM_analysis_stage + +import KratosMultiphysics.kratos_utilities as kratos_utils +import auxiliary_functions_for_tests + +this_working_dir_backup = os.getcwd() + +def GetFilePath(fileName): + return os.path.join(os.path.dirname(os.path.realpath(__file__)), fileName) + +class ForcesAndMomentsTestSolution(KratosMultiphysics.DEMApplication.DEM_analysis_stage.DEMAnalysisStage, KratosUnittest.TestCase): + + @classmethod + def GetMainPath(self): + return os.path.join(os.path.dirname(os.path.realpath(__file__)), "forces_and_moments_tests_files") + + def GetProblemNameWithPath(self): + return os.path.join(self.main_path, self.DEM_parameters["problem_name"].GetString()) + + def FinalizeSolutionStep(self): + super().FinalizeSolutionStep() + tolerance = 1e-3 + if self.time > 0.099999 and self.time < 0.100001: + for node in self.spheres_model_part.Nodes: + velocity = node.GetSolutionStepValue(Kratos.VELOCITY) + angular_velocity = node.GetSolutionStepValue(Kratos.ANGULAR_VELOCITY) + if node.Id == 1: + expected_value = 0.000955 + self.CheckValueOfVelocity(velocity, 0, expected_value, tolerance) + expected_value = -0.980986 + self.CheckValueOfVelocity(velocity, 1, expected_value, tolerance) + expected_value = -0.000312 + self.CheckValueOfVelocity(velocity, 2, expected_value, tolerance) + expected_value = -0.001194 + self.CheckValueOfVelocity(angular_velocity, 0, expected_value, tolerance) + expected_value = 0.000716 + self.CheckValueOfVelocity(angular_velocity, 1, expected_value, tolerance) + expected_value = 0.000718 + self.CheckValueOfVelocity(angular_velocity, 2, expected_value, tolerance) + if node.Id == 2: + expected_value = 0.048 + self.CheckValueOfVelocity(velocity, 0, expected_value, tolerance) + expected_value = -0.986 + self.CheckValueOfVelocity(velocity, 1, expected_value, tolerance) + expected_value = 0.043 + self.CheckValueOfVelocity(velocity, 2, expected_value, tolerance) + expected_value = 0.587 + self.CheckValueOfVelocity(angular_velocity, 0, expected_value, tolerance) + expected_value = 0.006 + self.CheckValueOfVelocity(angular_velocity, 1, expected_value, tolerance) + expected_value = 0.084 + self.CheckValueOfVelocity(angular_velocity, 2, expected_value, tolerance) + + if self.time > 0.299999 and self.time < 0.300001: + for node in self.rigid_face_model_part.Nodes: + velocity = node.GetSolutionStepValue(Kratos.VELOCITY) + angular_velocity = node.GetSolutionStepValue(Kratos.ANGULAR_VELOCITY) + if node.Id == 4: + expected_value = -85.265 + self.CheckValueOfVelocity(velocity, 0, expected_value, tolerance) + expected_value = 157.177 + self.CheckValueOfVelocity(velocity, 1, expected_value, tolerance) + expected_value = 32.412 + self.CheckValueOfVelocity(velocity, 2, expected_value, tolerance) + if node.Id == 13: + expected_value = 6309.350 + self.CheckValueOfVelocity(velocity, 0, expected_value, tolerance) + expected_value = 37395.854 + self.CheckValueOfVelocity(velocity, 1, expected_value, tolerance) + expected_value = -13433.566 + self.CheckValueOfVelocity(velocity, 2, expected_value, tolerance) + + def CheckValueOfVelocity(self, velocity, component, expected_value, tolerance): + self.assertAlmostEqual(velocity[component], expected_value, delta=tolerance) + + def CheckValueOfAngularVelocity(self, angular_velocity, component, expected_value, tolerance): + self.assertAlmostEqual(angular_velocity[component], expected_value, delta=tolerance) + +class TestExternalForcesAndMoments(KratosUnittest.TestCase): + + def setUp(self): + pass + + @classmethod + def test_ForcesAndMoments(self): + path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "forces_and_moments_tests_files") + parameters_file_name = os.path.join(path, "ProjectParametersDEM.json") + model = Kratos.Model() + auxiliary_functions_for_tests.CreateAndRunStageInSelectedNumberOfOpenMPThreads(ForcesAndMomentsTestSolution, model, parameters_file_name, 1) + + def tearDown(self): + file_to_remove = os.path.join("forces_and_moments_tests_files", "TimesPartialRelease") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("forces_and_moments_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + os.chdir(this_working_dir_backup) + + +if __name__ == "__main__": + Kratos.Logger.GetDefaultOutput().SetSeverity(Logger.Severity.WARNING) + KratosUnittest.main() diff --git a/applications/DEMApplication/tests/test_friction_decay.py b/applications/DEMApplication/tests/test_friction_decay.py new file mode 100644 index 000000000000..c04f200fc116 --- /dev/null +++ b/applications/DEMApplication/tests/test_friction_decay.py @@ -0,0 +1,66 @@ +import os +import KratosMultiphysics as Kratos +from KratosMultiphysics import Logger +Logger.GetDefaultOutput().SetSeverity(Logger.Severity.WARNING) +import KratosMultiphysics.KratosUnittest as KratosUnittest +import KratosMultiphysics.DEMApplication.DEM_analysis_stage as DEM_analysis_stage + +import KratosMultiphysics.kratos_utilities as kratos_utils + +import auxiliary_functions_for_tests + +this_working_dir_backup = os.getcwd() + +def GetFilePath(fileName): + return os.path.join(os.path.dirname(os.path.realpath(__file__)), fileName) + +class FrictionDecayTestSolution(DEM_analysis_stage.DEMAnalysisStage, KratosUnittest.TestCase): + + @classmethod + def GetMainPath(self): + return os.path.join(os.path.dirname(os.path.realpath(__file__)), "friction_decay_tests_files") + + def GetProblemNameWithPath(self): + return os.path.join(self.main_path, self.DEM_parameters["problem_name"].GetString()) + + def FinalizeSolutionStep(self): + super().FinalizeSolutionStep() + tolerance = 1e-4 + for node in self.spheres_model_part.Nodes: + total_force = node.GetSolutionStepValue(Kratos.TOTAL_FORCES) + if self.time > 0.0499999 and self.time < 0.0500001: + if node.Id == 1: + self.assertAlmostEqual(total_force[0], -4.406849, delta=tolerance) + if node.Id == 2: + self.assertAlmostEqual(total_force[0], -6.480977, delta=tolerance) + if node.Id == 3: + self.assertAlmostEqual(total_force[0], -4.392052, delta=tolerance) + if node.Id == 4: + self.assertAlmostEqual(total_force[0], -5.724009, delta=tolerance) + if node.Id == 5: + self.assertAlmostEqual(total_force[0], -4.392052, delta=tolerance) + if node.Id == 6: + self.assertAlmostEqual(total_force[0], -4.406849, delta=tolerance) + +class TestFrictionDecay(KratosUnittest.TestCase): + + def setUp(self): + pass + + @classmethod + def test_Friction_Decay(self): + path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "friction_decay_tests_files") + parameters_file_name = os.path.join(path, "ProjectParametersDEM.json") + model = Kratos.Model() + auxiliary_functions_for_tests.CreateAndRunStageInSelectedNumberOfOpenMPThreads(FrictionDecayTestSolution, model, parameters_file_name, 1) + + def tearDown(self): + file_to_remove = os.path.join("friction_decay_tests_files", "TimesPartialRelease") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + + os.chdir(this_working_dir_backup) + + +if __name__ == "__main__": + Kratos.Logger.GetDefaultOutput().SetSeverity(Logger.Severity.WARNING) + KratosUnittest.main() diff --git a/applications/DEMApplication/tests/test_glued_particles.py b/applications/DEMApplication/tests/test_glued_particles.py index e285caaff9c9..d316e133173b 100644 --- a/applications/DEMApplication/tests/test_glued_particles.py +++ b/applications/DEMApplication/tests/test_glued_particles.py @@ -57,7 +57,8 @@ def test_Glued_Particles_1(self): def tearDown(self): file_to_remove = os.path.join("glued_particles_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) - + file_to_remove = os.path.join("glued_particles_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_kinematic_constraints.py b/applications/DEMApplication/tests/test_kinematic_constraints.py index 8f66aa2c1351..f5008a9e1b0b 100644 --- a/applications/DEMApplication/tests/test_kinematic_constraints.py +++ b/applications/DEMApplication/tests/test_kinematic_constraints.py @@ -68,11 +68,61 @@ def FinalizeSolutionStep(self): self.CheckValueOfAngularVelocity(angular_velocity, 1, expected_value, tolerance) expected_value = -10.0 self.CheckValueOfAngularVelocity(angular_velocity, 2, expected_value, tolerance) + if node.Id == 4: if self.time > 0.22 and self.time < 0.25: expected_value = 0.2192 self.CheckValueOfAngularVelocity(angular_velocity, 2, expected_value, tolerance) + if node.Id == 5: + if self.time > 0.5999 and self.time < 0.6001: + expected_value = 6.000 + self.CheckValueOfAngularVelocity(velocity, 0, expected_value, tolerance) + expected_value = 5.998 + self.CheckValueOfAngularVelocity(velocity, 1, expected_value, tolerance) + expected_value = 6.000 + self.CheckValueOfAngularVelocity(velocity, 2, expected_value, tolerance) + expected_value = 6.000 + self.CheckValueOfAngularVelocity(angular_velocity, 0, expected_value, tolerance) + expected_value = 6.000 + self.CheckValueOfAngularVelocity(angular_velocity, 1, expected_value, tolerance) + expected_value = 6.000 + self.CheckValueOfAngularVelocity(angular_velocity, 2, expected_value, tolerance) + + for node in self.rigid_face_model_part.Nodes: + velocity = node.GetSolutionStepValue(Kratos.VELOCITY) + angular_velocity = node.GetSolutionStepValue(Kratos.ANGULAR_VELOCITY) + + if node.Id == 10: + if self.time > 0.5999 and self.time < 0.6001: + expected_value = -0.975 + self.CheckValueOfAngularVelocity(velocity, 0, expected_value, tolerance) + expected_value = -1.062 + self.CheckValueOfAngularVelocity(velocity, 1, expected_value, tolerance) + expected_value = 9.664 + self.CheckValueOfAngularVelocity(velocity, 2, expected_value, tolerance) + expected_value = 5.017 + self.CheckValueOfAngularVelocity(angular_velocity, 0, expected_value, tolerance) + expected_value = -1.200 + self.CheckValueOfAngularVelocity(angular_velocity, 1, expected_value, tolerance) + expected_value = 1.000 + self.CheckValueOfAngularVelocity(angular_velocity, 2, expected_value, tolerance) + + if node.Id == 20: + if self.time > 0.5999 and self.time < 0.6001: + expected_value = 7.788 + self.CheckValueOfAngularVelocity(velocity, 0, expected_value, tolerance) + expected_value = 0.262 + self.CheckValueOfAngularVelocity(velocity, 1, expected_value, tolerance) + expected_value = 0.894 + self.CheckValueOfAngularVelocity(velocity, 2, expected_value, tolerance) + expected_value = 0.450 + self.CheckValueOfAngularVelocity(angular_velocity, 0, expected_value, tolerance) + expected_value = 2.400 + self.CheckValueOfAngularVelocity(angular_velocity, 1, expected_value, tolerance) + expected_value = 5.400 + self.CheckValueOfAngularVelocity(angular_velocity, 2, expected_value, tolerance) + def CheckValueOfVelocity(self, velocity, component, expected_value, tolerance): self.assertAlmostEqual(velocity[component], expected_value, delta=tolerance) @@ -91,11 +141,11 @@ def test_KinematicConstraints_1(self): model = Kratos.Model() auxiliary_functions_for_tests.CreateAndRunStageInSelectedNumberOfOpenMPThreads(KinematicConstraintsTestSolution, model, parameters_file_name, 1) - def tearDown(self): file_to_remove = os.path.join("kinematic_constraints_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) - + file_to_remove = os.path.join("kinematic_constraints_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DEMApplication/tests/test_post_process.py b/applications/DEMApplication/tests/test_post_process.py index aa2c37032a40..3212a4b9a5ab 100644 --- a/applications/DEMApplication/tests/test_post_process.py +++ b/applications/DEMApplication/tests/test_post_process.py @@ -49,6 +49,8 @@ def test_gid_printing_many_results(self): def tearDown(self): file_to_remove = os.path.join("post_process_tests_files", "TimesPartialRelease") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) + file_to_remove = os.path.join("post_process_tests_files", "flux_data_new.hdf5") + kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) file_to_remove = os.path.join("post_process_tests_files", "ringcluster3D.clu") kratos_utils.DeleteFileIfExisting(GetFilePath(file_to_remove)) os.chdir(this_working_dir_backup) diff --git a/applications/DamApplication/CMakeLists.txt b/applications/DamApplication/CMakeLists.txt index b150e06122b6..7f799111ee8b 100755 --- a/applications/DamApplication/CMakeLists.txt +++ b/applications/DamApplication/CMakeLists.txt @@ -121,6 +121,12 @@ pybind11_add_module(KratosDamApplication MODULE THIN_LTO ${KRATOS_DAM_APPLICATIO target_link_libraries(KratosDamApplication PRIVATE KratosDamCore) set_target_properties(KratosDamApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosDamCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosDamApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosDamApplication PROPERTIES SUFFIX .pyd) @@ -131,12 +137,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosDamApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosDamCore) - cotire(KratosDamApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/DamApplication.py KratosMultiphysics/DamApplication/__init__.py ) diff --git a/applications/DamApplication/custom_strategies/schemes/dam_P_scheme.hpp b/applications/DamApplication/custom_strategies/schemes/dam_P_scheme.hpp index 74a2c5ccb271..68095c0bde9e 100644 --- a/applications/DamApplication/custom_strategies/schemes/dam_P_scheme.hpp +++ b/applications/DamApplication/custom_strategies/schemes/dam_P_scheme.hpp @@ -388,7 +388,7 @@ class DamPScheme : public Scheme { KRATOS_TRY - int NumThreads = OpenMPUtils::GetNumThreads(); + int NumThreads = ParallelUtilities::GetNumThreads(); OpenMPUtils::PartitionVector DofSetPartition; OpenMPUtils::DivideInPartitions(rDofSet.size(), NumThreads, DofSetPartition); diff --git a/applications/DamApplication/custom_strategies/schemes/dam_UP_scheme.hpp b/applications/DamApplication/custom_strategies/schemes/dam_UP_scheme.hpp index 9808a13103af..ed94a27f8c38 100644 --- a/applications/DamApplication/custom_strategies/schemes/dam_UP_scheme.hpp +++ b/applications/DamApplication/custom_strategies/schemes/dam_UP_scheme.hpp @@ -50,7 +50,7 @@ class DamUPScheme : public Scheme //Allocate auxiliary memory - int NumThreads = OpenMPUtils::GetNumThreads(); + int NumThreads = ParallelUtilities::GetNumThreads(); mMassMatrix.resize(NumThreads); mAccelerationVector.resize(NumThreads); mDampingMatrix.resize(NumThreads); @@ -508,7 +508,7 @@ class DamUPScheme : public Scheme { KRATOS_TRY - int NumThreads = OpenMPUtils::GetNumThreads(); + int NumThreads = ParallelUtilities::GetNumThreads(); OpenMPUtils::PartitionVector DofSetPartition; OpenMPUtils::DivideInPartitions(rDofSet.size(), NumThreads, DofSetPartition); diff --git a/applications/DamApplication/custom_strategies/schemes/incrementalupdate_static_damped_smoothing_scheme.hpp b/applications/DamApplication/custom_strategies/schemes/incrementalupdate_static_damped_smoothing_scheme.hpp index 3563d0db0b37..5f24153b98a4 100644 --- a/applications/DamApplication/custom_strategies/schemes/incrementalupdate_static_damped_smoothing_scheme.hpp +++ b/applications/DamApplication/custom_strategies/schemes/incrementalupdate_static_damped_smoothing_scheme.hpp @@ -45,7 +45,7 @@ class IncrementalUpdateStaticDampedSmoothingScheme : public IncrementalUpdateSta mRayleighBeta = rayleigh_k; //Allocate auxiliary memory - int NumThreads = OpenMPUtils::GetNumThreads(); + int NumThreads = ParallelUtilities::GetNumThreads(); mDampingMatrix.resize(NumThreads); mVelocityVector.resize(NumThreads); @@ -124,7 +124,7 @@ class IncrementalUpdateStaticDampedSmoothingScheme : public IncrementalUpdateSta //const double DeltaTime = rModelPart.GetProcessInfo()[DELTA_TIME]; // Updating time derivatives (nodally for efficiency) - const unsigned int NumThreads = OpenMPUtils::GetNumThreads(); + const unsigned int NumThreads = ParallelUtilities::GetNumThreads(); OpenMPUtils::PartitionVector NodePartition; OpenMPUtils::DivideInPartitions(rModelPart.Nodes().size(), NumThreads, NodePartition); @@ -167,7 +167,7 @@ class IncrementalUpdateStaticDampedSmoothingScheme : public IncrementalUpdateSta { KRATOS_TRY; - int NumThreads = OpenMPUtils::GetNumThreads(); + int NumThreads = ParallelUtilities::GetNumThreads(); OpenMPUtils::PartitionVector DofSetPartition; OpenMPUtils::DivideInPartitions(rDofSet.size(), NumThreads, DofSetPartition); diff --git a/applications/DamApplication/custom_strategies/schemes/trilinos_dam_UP_scheme.hpp b/applications/DamApplication/custom_strategies/schemes/trilinos_dam_UP_scheme.hpp index 51cbd2b6cef3..a11904b33b8f 100644 --- a/applications/DamApplication/custom_strategies/schemes/trilinos_dam_UP_scheme.hpp +++ b/applications/DamApplication/custom_strategies/schemes/trilinos_dam_UP_scheme.hpp @@ -1,4 +1,4 @@ -// +// // Project Name: KratosDamApplication $ // Last Modified by: $Author:Ignasi de Pouplana $ // Date: $Date: February 2017$ @@ -38,9 +38,9 @@ class TrilinosDamUPScheme : public DamUPScheme TrilinosDamUPScheme(double beta, double gamma, double rayleigh_m ,double rayleigh_k) : DamUPScheme(beta, gamma, rayleigh_m ,rayleigh_k), mImporterIsInitialized(false) {} - + //------------------------------------------------------------------------------------ - + ///Destructor virtual ~TrilinosDamUPScheme() {} @@ -54,31 +54,31 @@ class TrilinosDamUPScheme : public DamUPScheme TSystemVectorType& b) { KRATOS_TRY - + if (DofImporterIsInitialized() == false) { this->InitializeDofImporter(rDofSet,Dx); } const int system_size = TSparseSpace::Size1(A); - - const unsigned int NumThreads = OpenMPUtils::GetNumThreads(); + + const unsigned int NumThreads = ParallelUtilities::GetNumThreads(); // Defining a temporary vector to gather all of the values needed Epetra_Vector temp( mpDofImporter->TargetMap() ); - + // Importing in the new temp vector the values const unsigned int ierr = temp.Import(Dx,*mpDofImporter,Insert); - if(ierr != 0) + if(ierr != 0) { KRATOS_THROW_ERROR(std::logic_error,"Epetra failure found",""); } - + double* temp_values; //DO NOT make delete of this one!! temp.ExtractView( &temp_values ); Dx.Comm().Barrier(); - + // Update of displacement (by DOF) OpenMPUtils::PartitionVector DofPartition; OpenMPUtils::DivideInPartitions(rDofSet.size(), NumThreads, DofPartition); @@ -101,7 +101,7 @@ class TrilinosDamUPScheme : public DamUPScheme } } } - + this->UpdateVariablesDerivatives(r_model_part); KRATOS_CATCH( "" ) @@ -112,7 +112,7 @@ class TrilinosDamUPScheme : public DamUPScheme void Clear() { BaseType::Clear(); - + mpDofImporter.reset(); mImporterIsInitialized = false; } @@ -127,9 +127,9 @@ class TrilinosDamUPScheme : public DamUPScheme //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- protected: - + /// Member Variables - + //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -189,9 +189,9 @@ class TrilinosDamUPScheme : public DamUPScheme //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- private: - + /// Member Variables - + bool mImporterIsInitialized; Kratos::shared_ptr mpDofImporter; diff --git a/applications/DamApplication/custom_utilities/mapping_variables_2D_utilities.hpp b/applications/DamApplication/custom_utilities/mapping_variables_2D_utilities.hpp index 272e94ec3497..ed0da1224eda 100644 --- a/applications/DamApplication/custom_utilities/mapping_variables_2D_utilities.hpp +++ b/applications/DamApplication/custom_utilities/mapping_variables_2D_utilities.hpp @@ -495,7 +495,7 @@ class MappingVariables2DUtilities ModelPart& rModelPart) { // Compute X and Y limits of the current geometry - unsigned int NumThreads = OpenMPUtils::GetNumThreads(); + unsigned int NumThreads = ParallelUtilities::GetNumThreads(); std::vector X_max_partition(NumThreads); std::vector X_min_partition(NumThreads); std::vector Y_max_partition(NumThreads); diff --git a/applications/DamApplication/custom_utilities/mapping_variables_3D_utilities.hpp b/applications/DamApplication/custom_utilities/mapping_variables_3D_utilities.hpp index f14391f642b7..a689352a8bbf 100644 --- a/applications/DamApplication/custom_utilities/mapping_variables_3D_utilities.hpp +++ b/applications/DamApplication/custom_utilities/mapping_variables_3D_utilities.hpp @@ -535,7 +535,7 @@ class MappingVariables3DUtilities { // Compute X, Y and Z limits of the current geometry - unsigned int NumThreads = OpenMPUtils::GetNumThreads(); + unsigned int NumThreads = ParallelUtilities::GetNumThreads(); std::vector X_max_partition(NumThreads); std::vector X_min_partition(NumThreads); std::vector Y_max_partition(NumThreads); diff --git a/applications/DelaunayMeshingApplication/CMakeLists.txt b/applications/DelaunayMeshingApplication/CMakeLists.txt index a7301a3fbfce..d94b3eaed3d7 100644 --- a/applications/DelaunayMeshingApplication/CMakeLists.txt +++ b/applications/DelaunayMeshingApplication/CMakeLists.txt @@ -92,6 +92,12 @@ pybind11_add_module(KratosDelaunayMeshingApplication MODULE ${KRATOS_DELAUNAY_ME target_link_libraries(KratosDelaunayMeshingApplication PRIVATE KratosDelaunayMeshingCore) set_target_properties(KratosDelaunayMeshingApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosDelaunayMeshingCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosDelaunayMeshingApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES) # message("TestApplication subdir inc_dirs = ${inc_dirs}") @@ -105,12 +111,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosDelaunayMeshingApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosDelaunayMeshingCore) - cotire(KratosDelaunayMeshingApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/DelaunayMeshingApplication.py KratosMultiphysics/DelaunayMeshingApplication/__init__.py ) diff --git a/applications/DemStructuresCouplingApplication/CMakeLists.txt b/applications/DemStructuresCouplingApplication/CMakeLists.txt index b215fe41bff4..647d0b2f135f 100755 --- a/applications/DemStructuresCouplingApplication/CMakeLists.txt +++ b/applications/DemStructuresCouplingApplication/CMakeLists.txt @@ -42,6 +42,11 @@ pybind11_add_module(KratosDemStructuresCouplingApplication MODULE THIN_LTO ${KRA target_link_libraries(KratosDemStructuresCouplingApplication PUBLIC KratosDemStructuresCouplingCore) set_target_properties(KratosDemStructuresCouplingApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosDemStructuresCouplingCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosDemStructuresCouplingApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) if(${ACTIVATE_DEBUG_MACRO} MATCHES ON) #MSI: Flag defined for debug Macro add_definitions(-DDEBUG_MACRO) @@ -57,12 +62,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosDemStructuresCouplingApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosDemStructuresCouplingCore) - cotire(KratosDemStructuresCouplingApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/DemStructuresCouplingApplication.py KratosMultiphysics/DemStructuresCouplingApplication/__init__.py ) diff --git a/applications/DemStructuresCouplingApplication/custom_utilities/dem_structures_coupling_utilities.h b/applications/DemStructuresCouplingApplication/custom_utilities/dem_structures_coupling_utilities.h index 7ff85dfef44b..b7af0c7a7655 100644 --- a/applications/DemStructuresCouplingApplication/custom_utilities/dem_structures_coupling_utilities.h +++ b/applications/DemStructuresCouplingApplication/custom_utilities/dem_structures_coupling_utilities.h @@ -85,7 +85,7 @@ void TransferStructuresSkinToDem(ModelPart& r_source_model_part, ModelPart& r_de } std::string CheckProvidedProperties(Properties::Pointer props) { - std::vector* > list_of_variables_double_to_check = {&STATIC_FRICTION, &DYNAMIC_FRICTION, &WALL_COHESION, &SEVERITY_OF_WEAR, &IMPACT_WEAR_SEVERITY, &BRINELL_HARDNESS, &YOUNG_MODULUS, &POISSON_RATIO}; + std::vector* > list_of_variables_double_to_check = {&STATIC_FRICTION, &DYNAMIC_FRICTION, &FRICTION_DECAY, &WALL_COHESION, &SEVERITY_OF_WEAR, &IMPACT_WEAR_SEVERITY, &BRINELL_HARDNESS, &YOUNG_MODULUS, &POISSON_RATIO}; std::vector* > list_of_variables_bool_to_check = {&COMPUTE_WEAR}; for (int i=0; i<(int)list_of_variables_double_to_check.size(); i++) { if(!props->Has(*list_of_variables_double_to_check[i])) return list_of_variables_double_to_check[i]->Name(); diff --git a/applications/ExaquteSandboxApplication/CMakeLists.txt b/applications/ExaquteSandboxApplication/CMakeLists.txt index 647de030a815..4831bef613dd 100644 --- a/applications/ExaquteSandboxApplication/CMakeLists.txt +++ b/applications/ExaquteSandboxApplication/CMakeLists.txt @@ -43,6 +43,12 @@ pybind11_add_module(KratosExaquteSandboxApplication MODULE THIN_LTO ${KRATOS_EXA target_link_libraries(KratosExaquteSandboxApplication PRIVATE KratosExaquteSandboxCore ) set_target_properties(KratosExaquteSandboxApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosExaquteSandboxCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosExaquteSandboxApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosExaquteSandboxApplication PROPERTIES SUFFIX .pyd) @@ -53,11 +59,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosExaquteSandboxApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosExaquteSandboxApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/ExaquteSandboxApplication.py KratosMultiphysics/ExaquteSandboxApplication/__init__.py ) diff --git a/applications/ExternalSolversApplication/CMakeLists.txt b/applications/ExternalSolversApplication/CMakeLists.txt index e3304878f0f6..89cbddd76d12 100644 --- a/applications/ExternalSolversApplication/CMakeLists.txt +++ b/applications/ExternalSolversApplication/CMakeLists.txt @@ -89,6 +89,11 @@ endif(${INCLUDE_PASTIX} MATCHES ON) set_target_properties(KratosExternalSolversApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosExternalSolversApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd # if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") # set_target_properties(KratosExternalSolversApplication PROPERTIES SUFFIX .pyd) @@ -99,11 +104,6 @@ set_target_properties(KratosExternalSolversApplication PROPERTIES PREFIX "") # set_target_properties(KratosExternalSolversApplication PROPERTIES SUFFIX .so) # endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Add Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosExternalSolversApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/ExternalSolversApplication.py KratosMultiphysics/ExternalSolversApplication/__init__.py ) diff --git a/applications/FSIApplication/CMakeLists.txt b/applications/FSIApplication/CMakeLists.txt index 28becda3de2d..db7bd0b5c351 100644 --- a/applications/FSIApplication/CMakeLists.txt +++ b/applications/FSIApplication/CMakeLists.txt @@ -32,6 +32,11 @@ pybind11_add_module(KratosFSIApplication MODULE THIN_LTO ${KRATOS_FSI_APPLICATIO target_link_libraries(KratosFSIApplication PRIVATE KratosCore ) set_target_properties(KratosFSIApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosFSIApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosFSIApplication PROPERTIES SUFFIX .pyd) @@ -42,11 +47,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosFSIApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosFSIApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/FSIApplication.py KratosMultiphysics/FSIApplication/__init__.py ) diff --git a/applications/FSIApplication/custom_python/add_convergence_accelerators_to_python.cpp b/applications/FSIApplication/custom_python/add_convergence_accelerators_to_python.cpp index 31bebe39d6cf..853aa6353abe 100644 --- a/applications/FSIApplication/custom_python/add_convergence_accelerators_to_python.cpp +++ b/applications/FSIApplication/custom_python/add_convergence_accelerators_to_python.cpp @@ -27,6 +27,7 @@ #include "custom_utilities/mvqn_convergence_accelerator.hpp" #include "custom_utilities/mvqn_recursive_convergence_accelerator.hpp" #include "custom_utilities/aitken_convergence_accelerator.hpp" +#include "custom_utilities/ibqn_mvqn_convergence_accelerator.h" namespace Kratos { @@ -63,7 +64,16 @@ void AddConvergenceAcceleratorsToPython(pybind11::module &m) typedef typename MVQNFullJacobianConvergenceAcceleratorType::Pointer MVQNFullJacobianConvergenceAcceleratorPointerType; py::class_(m, "MVQNFullJacobianConvergenceAccelerator") .def(py::init()) - .def(py::init()) + .def(py::init()) + ; + + // MVQN convergence accelerator + typedef IBQNMVQNConvergenceAccelerator IBQNMVQNConvergenceAcceleratorType; + typedef typename IBQNMVQNConvergenceAcceleratorType::Pointer IBQNMVQNConvergenceAcceleratorPointerType; + py::class_(m, "IBQNMVQNConvergenceAccelerator") + .def(py::init()) + .def("UpdateSolutionLeft", &IBQNMVQNConvergenceAcceleratorType::UpdateSolutionLeft) + .def("UpdateSolutionRight", &IBQNMVQNConvergenceAcceleratorType::UpdateSolutionRight) ; // MVQN recursive convergence accelerator diff --git a/applications/FSIApplication/custom_python/add_custom_utilities_to_python.cpp b/applications/FSIApplication/custom_python/add_custom_utilities_to_python.cpp index 98cd36622432..74b96efe0d7a 100644 --- a/applications/FSIApplication/custom_python/add_custom_utilities_to_python.cpp +++ b/applications/FSIApplication/custom_python/add_custom_utilities_to_python.cpp @@ -45,7 +45,6 @@ void AddCustomUtilitiesToPython(pybind11::module &m) py::class_, PartitionedFSIUtilities::Pointer>(m,"PartitionedFSIUtilitiesDouble2D") .def(py::init<>()) - .def("CopySkinToElements", &PartitionedFSIUtilities::CopySkinToElements) .def("GetInterfaceArea", &PartitionedFSIUtilities::GetInterfaceArea) .def("GetInterfaceResidualSize", &PartitionedFSIUtilities::GetInterfaceResidualSize) .def("UpdateInterfaceValues", &PartitionedFSIUtilities::UpdateInterfaceValues) @@ -55,13 +54,16 @@ void AddCustomUtilitiesToPython(pybind11::module &m) .def("ComputeAndPrintStructureInterfaceNorms", &PartitionedFSIUtilities::ComputeAndPrintStructureInterfaceNorms) .def("CheckCurrentCoordinatesFluid", &PartitionedFSIUtilities::CheckCurrentCoordinatesFluid) .def("CheckCurrentCoordinatesStructure", &PartitionedFSIUtilities::CheckCurrentCoordinatesStructure) + .def("SetUpInterfaceVector", &PartitionedFSIUtilities::SetUpInterfaceVector) .def("InitializeInterfaceVector", &PartitionedFSIUtilities::InitializeInterfaceVector) - .def("CreateCouplingElementBasedSkin", &PartitionedFSIUtilities::CreateCouplingElementBasedSkin) - .def("EmbeddedPressureToPositiveFacePressureInterpolator", &PartitionedFSIUtilities::EmbeddedPressureToPositiveFacePressureInterpolator); + .def("CreateCouplingSkin", &PartitionedFSIUtilities::CreateCouplingSkin) + .def("EmbeddedPressureToPositiveFacePressureInterpolator", &PartitionedFSIUtilities::EmbeddedPressureToPositiveFacePressureInterpolator) + .def("CalculateTractionFromPressureValues", [](PartitionedFSIUtilities& rPartitionedFSIUtilities, ModelPart& rModelPart, const Variable& rPressureVariable, const Variable>& rTractionVariable, const bool SwapTractionSign){rPartitionedFSIUtilities.CalculateTractionFromPressureValues(rModelPart, rPressureVariable, rTractionVariable, SwapTractionSign);}) + .def("CalculateTractionFromPressureValues", [](PartitionedFSIUtilities& rPartitionedFSIUtilities, ModelPart& rModelPart, const Variable& rPositivePressureVariable, const Variable& rNegativePressureVariable, const Variable>& rTractionVariable, const bool SwapTractionSign){rPartitionedFSIUtilities.CalculateTractionFromPressureValues(rModelPart, rPositivePressureVariable, rNegativePressureVariable, rTractionVariable, SwapTractionSign);}) + ; py::class_, 2>, PartitionedFSIUtilities, 2>::Pointer>(m, "PartitionedFSIUtilitiesArray2D") .def(py::init<>()) - .def("CopySkinToElements", &PartitionedFSIUtilities, 2>::CopySkinToElements) .def("GetInterfaceArea", &PartitionedFSIUtilities, 2>::GetInterfaceArea) .def("GetInterfaceResidualSize", &PartitionedFSIUtilities, 2>::GetInterfaceResidualSize) .def("UpdateInterfaceValues", &PartitionedFSIUtilities, 2>::UpdateInterfaceValues) @@ -71,13 +73,16 @@ void AddCustomUtilitiesToPython(pybind11::module &m) .def("ComputeAndPrintStructureInterfaceNorms", &PartitionedFSIUtilities, 2>::ComputeAndPrintStructureInterfaceNorms) .def("CheckCurrentCoordinatesFluid", &PartitionedFSIUtilities, 2>::CheckCurrentCoordinatesFluid) .def("CheckCurrentCoordinatesStructure", &PartitionedFSIUtilities, 2>::CheckCurrentCoordinatesStructure) + .def("SetUpInterfaceVector", &PartitionedFSIUtilities, 2>::SetUpInterfaceVector) .def("InitializeInterfaceVector", &PartitionedFSIUtilities, 2>::InitializeInterfaceVector) - .def("CreateCouplingElementBasedSkin", &PartitionedFSIUtilities, 2>::CreateCouplingElementBasedSkin) - .def("EmbeddedPressureToPositiveFacePressureInterpolator", &PartitionedFSIUtilities, 2>::EmbeddedPressureToPositiveFacePressureInterpolator); + .def("CreateCouplingSkin", &PartitionedFSIUtilities, 2>::CreateCouplingSkin) + .def("EmbeddedPressureToPositiveFacePressureInterpolator", &PartitionedFSIUtilities, 2>::EmbeddedPressureToPositiveFacePressureInterpolator) + .def("CalculateTractionFromPressureValues", [](PartitionedFSIUtilities,2>& rPartitionedFSIUtilities, ModelPart& rModelPart, const Variable& rPressureVariable, const Variable>& rTractionVariable, const bool SwapTractionSign){rPartitionedFSIUtilities.CalculateTractionFromPressureValues(rModelPart, rPressureVariable, rTractionVariable, SwapTractionSign);}) + .def("CalculateTractionFromPressureValues", [](PartitionedFSIUtilities,2>& rPartitionedFSIUtilities, ModelPart& rModelPart, const Variable& rPositivePressureVariable, const Variable& rNegativePressureVariable, const Variable>& rTractionVariable, const bool SwapTractionSign){rPartitionedFSIUtilities.CalculateTractionFromPressureValues(rModelPart, rPositivePressureVariable, rNegativePressureVariable, rTractionVariable, SwapTractionSign);}) + ; py::class_, PartitionedFSIUtilities::Pointer>(m,"PartitionedFSIUtilitiesDouble3D") .def(py::init<>()) - .def("CopySkinToElements", &PartitionedFSIUtilities::CopySkinToElements) .def("GetInterfaceArea", &PartitionedFSIUtilities::GetInterfaceArea) .def("GetInterfaceResidualSize", &PartitionedFSIUtilities::GetInterfaceResidualSize) .def("UpdateInterfaceValues", &PartitionedFSIUtilities::UpdateInterfaceValues) @@ -87,13 +92,16 @@ void AddCustomUtilitiesToPython(pybind11::module &m) .def("ComputeAndPrintStructureInterfaceNorms", &PartitionedFSIUtilities::ComputeAndPrintStructureInterfaceNorms) .def("CheckCurrentCoordinatesFluid", &PartitionedFSIUtilities::CheckCurrentCoordinatesFluid) .def("CheckCurrentCoordinatesStructure", &PartitionedFSIUtilities::CheckCurrentCoordinatesStructure) + .def("SetUpInterfaceVector", &PartitionedFSIUtilities::SetUpInterfaceVector) .def("InitializeInterfaceVector", &PartitionedFSIUtilities::InitializeInterfaceVector) - .def("CreateCouplingElementBasedSkin", &PartitionedFSIUtilities::CreateCouplingElementBasedSkin) - .def("EmbeddedPressureToPositiveFacePressureInterpolator", &PartitionedFSIUtilities::EmbeddedPressureToPositiveFacePressureInterpolator); + .def("CreateCouplingSkin", &PartitionedFSIUtilities::CreateCouplingSkin) + .def("EmbeddedPressureToPositiveFacePressureInterpolator", &PartitionedFSIUtilities::EmbeddedPressureToPositiveFacePressureInterpolator) + .def("CalculateTractionFromPressureValues", [](PartitionedFSIUtilities& rPartitionedFSIUtilities, ModelPart& rModelPart, const Variable& rPressureVariable, const Variable>& rTractionVariable, const bool SwapTractionSign){rPartitionedFSIUtilities.CalculateTractionFromPressureValues(rModelPart, rPressureVariable, rTractionVariable, SwapTractionSign);}) + .def("CalculateTractionFromPressureValues", [](PartitionedFSIUtilities& rPartitionedFSIUtilities, ModelPart& rModelPart, const Variable& rPositivePressureVariable, const Variable& rNegativePressureVariable, const Variable>& rTractionVariable, const bool SwapTractionSign){rPartitionedFSIUtilities.CalculateTractionFromPressureValues(rModelPart, rPositivePressureVariable, rNegativePressureVariable, rTractionVariable, SwapTractionSign);}) + ; py::class_,3>, PartitionedFSIUtilities,3>::Pointer>(m,"PartitionedFSIUtilitiesArray3D") .def(py::init<>()) - .def("CopySkinToElements", &PartitionedFSIUtilities,3>::CopySkinToElements) .def("GetInterfaceArea", &PartitionedFSIUtilities,3>::GetInterfaceArea) .def("GetInterfaceResidualSize", &PartitionedFSIUtilities,3>::GetInterfaceResidualSize) .def("UpdateInterfaceValues", &PartitionedFSIUtilities,3>::UpdateInterfaceValues) @@ -103,9 +111,13 @@ void AddCustomUtilitiesToPython(pybind11::module &m) .def("ComputeAndPrintStructureInterfaceNorms", &PartitionedFSIUtilities,3>::ComputeAndPrintStructureInterfaceNorms) .def("CheckCurrentCoordinatesFluid", &PartitionedFSIUtilities,3>::CheckCurrentCoordinatesFluid) .def("CheckCurrentCoordinatesStructure", &PartitionedFSIUtilities,3>::CheckCurrentCoordinatesStructure) + .def("SetUpInterfaceVector", &PartitionedFSIUtilities, 3>::SetUpInterfaceVector) .def("InitializeInterfaceVector", &PartitionedFSIUtilities,3>::InitializeInterfaceVector) - .def("CreateCouplingElementBasedSkin", &PartitionedFSIUtilities,3>::CreateCouplingElementBasedSkin) - .def("EmbeddedPressureToPositiveFacePressureInterpolator", &PartitionedFSIUtilities,3>::EmbeddedPressureToPositiveFacePressureInterpolator); + .def("CreateCouplingSkin", &PartitionedFSIUtilities,3>::CreateCouplingSkin) + .def("EmbeddedPressureToPositiveFacePressureInterpolator", &PartitionedFSIUtilities,3>::EmbeddedPressureToPositiveFacePressureInterpolator) + .def("CalculateTractionFromPressureValues", [](PartitionedFSIUtilities,3>& rPartitionedFSIUtilities, ModelPart& rModelPart, const Variable& rPressureVariable, const Variable>& rTractionVariable, const bool SwapTractionSign){rPartitionedFSIUtilities.CalculateTractionFromPressureValues(rModelPart, rPressureVariable, rTractionVariable, SwapTractionSign);}) + .def("CalculateTractionFromPressureValues", [](PartitionedFSIUtilities,3>& rPartitionedFSIUtilities, ModelPart& rModelPart, const Variable& rPositivePressureVariable, const Variable& rNegativePressureVariable, const Variable>& rTractionVariable, const bool SwapTractionSign){rPartitionedFSIUtilities.CalculateTractionFromPressureValues(rModelPart, rPositivePressureVariable, rNegativePressureVariable, rTractionVariable, SwapTractionSign);}) + ; } diff --git a/applications/FSIApplication/custom_utilities/aitken_convergence_accelerator.hpp b/applications/FSIApplication/custom_utilities/aitken_convergence_accelerator.hpp index 0669a6a95689..d1ab919a3754 100644 --- a/applications/FSIApplication/custom_utilities/aitken_convergence_accelerator.hpp +++ b/applications/FSIApplication/custom_utilities/aitken_convergence_accelerator.hpp @@ -73,9 +73,10 @@ class AitkenConvergenceAccelerator: public ConvergenceAccelerator +class MVQNFullJacobianConvergenceAccelerator; + +/** @brief Interface Block Newton convergence accelerator + * Interface Block Newton equations convergence accelerator + * @tparam TSparseSpace Linear algebra sparse space + * @tparam TDenseSpace Linear algebra dense space + */ +template +class IBQNMVQNConvergenceAccelerator: public ConvergenceAccelerator +{ +public: + + ///@name Type Definitions + ///@{ + KRATOS_CLASS_POINTER_DEFINITION( IBQNMVQNConvergenceAccelerator ); + + typedef ConvergenceAccelerator BaseType; + typedef typename BaseType::Pointer BaseTypePointer; + + typedef typename BaseType::DenseVectorType VectorType; + typedef typename BaseType::DenseVectorPointerType VectorPointerType; + + typedef typename BaseType::DenseMatrixType MatrixType; + typedef typename BaseType::DenseMatrixPointerType MatrixPointerType; + + typedef MVQNFullJacobianConvergenceAccelerator MVQNType; + typedef typename MVQNType::Pointer MVQNPointerType; + + ///@} + ///@name Life Cycle + ///@{ + + /** + * @brief Construct a new IBQNMVQNConvergenceAccelerator object + * MVQN convergence accelerator Json settings constructor + * @param rConvAcceleratorParameters Json string encapsulating the settings + */ + + explicit IBQNMVQNConvergenceAccelerator(Parameters rParameters) + { + Parameters mvqn_default_parameters(R"({ + "solver_type" : "IBQN_MVQN", + "w_0" : 0.825, + "abs_cut_off_tol" : 1e-8 + })"); + rParameters.ValidateAndAssignDefaults(mvqn_default_parameters); + + mInitialOmega = rParameters["w_0"].GetDouble(); + const double abs_cut_off_tol = rParameters["abs_cut_off_tol"].GetDouble(); + mpConvergenceAcceleratorLeft = Kratos::make_unique(mInitialOmega, abs_cut_off_tol, true); + mpConvergenceAcceleratorRight = Kratos::make_unique(mInitialOmega, abs_cut_off_tol, true); + } + + /** + * Copy Constructor. + */ + IBQNMVQNConvergenceAccelerator(const IBQNMVQNConvergenceAccelerator& rOther) = delete; + + /** + * Destructor. + */ + virtual ~IBQNMVQNConvergenceAccelerator(){} + + ///@} + ///@name Operators + ///@{ + + + ///@} + ///@name Operations + ///@{ + + void Initialize() override + { + KRATOS_TRY; + + mpConvergenceAcceleratorLeft->Initialize(); + mpConvergenceAcceleratorRight->Initialize(); + + KRATOS_CATCH( "" ); + } + + /** + * @brief Initialize the internal iteration counter + * This method initializes the convergence acceleratior iteration counter at the begining of the step. + */ + void InitializeSolutionStep() override + { + KRATOS_TRY; + + mConvergenceAcceleratorIteration = 0; + + mpConvergenceAcceleratorLeft->InitializeSolutionStep(); + mpConvergenceAcceleratorRight->InitializeSolutionStep(); + + KRATOS_CATCH( "" ); + } + + void InitializeNonLinearIteration() override + { + KRATOS_TRY; + + mpConvergenceAcceleratorLeft->InitializeNonLinearIteration(); + mpConvergenceAcceleratorRight->InitializeNonLinearIteration(); + + KRATOS_CATCH( "" ); + } + + /** + * @brief Performs the solution update + * This method computes the solution update using a Jacobian approximation. + * Such Jacobian approximation is computed with the MVQN (MultiVector Quasi-Newton method) algorithm. + * @param rResidualVector Residual vector from the residual evaluation + * @param rIterationGuess Current iteration guess to be corrected. Should be initialized to zero outside the convergence accelerator. + */ + void UpdateSolution( + const VectorType& rResidualVector, + VectorType& rIterationGuess) override + { + KRATOS_TRY; + + KRATOS_ERROR << "The UpdateSolution() method cannot be called in the interface block Newton case. Use either \'UpdateSolutionLeft\' or \'UpdateSolutionRight\'" << std::endl; + + KRATOS_CATCH( "" ); + } + + //TODO: CREATE AN INTERMEDIATE IBQN BASE CLASS + virtual void UpdateSolutionRight( + const VectorType& rForceInputVector, + const VectorType& rDisplacementOutputVector, + VectorType& rIterationGuess) + { + // Save the uncorrected force vector for the displacement update + auto p_uncor_disp_aux = Kratos::make_shared(rDisplacementOutputVector); + std::swap(mpUncorrectedDisplacementVector, p_uncor_disp_aux); + + // Update right inverse Jacobian approximation with the current information + mpConvergenceAcceleratorRight->UpdateInverseJacobianApproximation(rForceInputVector, rDisplacementOutputVector); + + VectorType right_correction(TSparseSpace::Size(rIterationGuess)); + if (!mFirstRightCorrectionPerformed) { + // Calculate the first correction as a fixed point relaxation + TSparseSpace::SetToZero(right_correction); + TSparseSpace::UnaliasedAdd(right_correction, mInitialOmega, rDisplacementOutputVector - rIterationGuess); + + // Update the first iteration correction flag + mFirstRightCorrectionPerformed = true; + + } else { + // Get the interface problem size + std::size_t problem_size = mpConvergenceAcceleratorRight->GetProblemSize(); + + // Get both left and inverse Jacobian + auto p_inv_jac_right = mpConvergenceAcceleratorRight->pGetInverseJacobianApproximation(); + auto p_inv_jac_left = mpConvergenceAcceleratorLeft->pGetInverseJacobianApproximation(); + + // Set the residual of the update problem to be solved + VectorType aux_RHS = rDisplacementOutputVector - rIterationGuess; + VectorType aux_right_onto_left(problem_size); + VectorType force_iteration_update = *mpUncorrectedForceVector - rForceInputVector; + TSparseSpace::Mult(*p_inv_jac_right, force_iteration_update, aux_right_onto_left); + TSparseSpace::UnaliasedAdd(aux_RHS, 1.0, aux_right_onto_left); + + // Set the LHS of the update problem to be solved + MatrixType aux_LHS = IdentityMatrix(problem_size, problem_size); + IndexPartition(problem_size).for_each( + VectorType(problem_size), + [&aux_LHS, &p_inv_jac_right, &p_inv_jac_left, &problem_size](std::size_t Col, VectorType& rAuxColumnTLS) + { + TDenseSpace::GetColumn(Col, *p_inv_jac_left, rAuxColumnTLS); + for (std::size_t row = 0; row < problem_size; ++row) { + aux_LHS(row,Col) -= TDenseSpace::RowDot(row, *p_inv_jac_right, rAuxColumnTLS); + } + }); + + // Calculate the correction + // Do the QR decomposition of (I - J_{S}J_{F}) and solve for the force update + QR qr_util; + qr_util.compute(problem_size, problem_size, &(aux_LHS)(0,0)); + qr_util.solve(&(aux_RHS)(0), &(right_correction)(0)); + } + + // Update the iteration guess + TSparseSpace::UnaliasedAdd(rIterationGuess, 1.0, right_correction); + } + + //TODO: CREATE AN INTERMEDIATE IBQN BASE CLASS + virtual void UpdateSolutionLeft( + const VectorType& rDisplacementInputVector, + const VectorType& rForceOutputVector, + VectorType& rIterationGuess) + { + KRATOS_TRY; + + // Save the uncorrected force vector for the displacement update + auto p_uncor_force_aux = Kratos::make_shared(rForceOutputVector); + std::swap(mpUncorrectedForceVector, p_uncor_force_aux); + + // Update left inverse Jacobian approximation with the current information + mpConvergenceAcceleratorLeft->UpdateInverseJacobianApproximation(rDisplacementInputVector, rForceOutputVector); + + VectorType left_correction(TSparseSpace::Size(rIterationGuess)); + if (!mFirstLeftCorrectionPerformed) { + // Do nothing in the first traction correction + // This means to set as correction the difference between the guess and the previous iteration + left_correction = rForceOutputVector - rIterationGuess; + + // Update the first iteration correction flag + mFirstLeftCorrectionPerformed = true; + + } else { + // Get the interface problem size + std::size_t problem_size = mpConvergenceAcceleratorLeft->GetProblemSize(); + + // Get both left and inverse Jacobian + auto p_inv_jac_left = mpConvergenceAcceleratorLeft->pGetInverseJacobianApproximation(); + auto p_inv_jac_right = mpConvergenceAcceleratorRight->pGetInverseJacobianApproximation(); + + // Set the residual of the update problem to be solved + VectorType aux_RHS = rForceOutputVector - rIterationGuess; + VectorType aux_left_onto_right(problem_size); + VectorType displacement_iteration_update = *mpUncorrectedDisplacementVector - rDisplacementInputVector; + TSparseSpace::Mult(*p_inv_jac_left, displacement_iteration_update, aux_left_onto_right); + TSparseSpace::UnaliasedAdd(aux_RHS, 1.0, aux_left_onto_right); + + // Set the LHS of the update problem to be solved + MatrixType aux_LHS = IdentityMatrix(problem_size, problem_size); + IndexPartition(problem_size).for_each( + VectorType(problem_size), + [&aux_LHS, &p_inv_jac_left, &p_inv_jac_right, &problem_size](std::size_t Col, VectorType& rAuxColumnTLS) + { + TDenseSpace::GetColumn(Col, *p_inv_jac_right, rAuxColumnTLS); + for (std::size_t row = 0; row < problem_size; ++row) { + aux_LHS(row,Col) -= TDenseSpace::RowDot(row, *p_inv_jac_left, rAuxColumnTLS); + } + }); + + // Calculate the correction + // Do the QR decomposition of (I - J_{F}J_{S}) and solve for the force update + QR qr_util; + qr_util.compute(problem_size, problem_size, &(aux_LHS)(0,0)); + qr_util.solve(&(aux_RHS)(0), &(left_correction)(0)); + } + + // Update the iteration guess + TSparseSpace::UnaliasedAdd(rIterationGuess, 1.0, left_correction); + + KRATOS_CATCH(""); + } + + /** + * @brief Do the MVQN variables update + * Updates the MVQN iteration variables for the next non-linear iteration + */ + void FinalizeNonLinearIteration() override + { + KRATOS_TRY; + + mConvergenceAcceleratorIteration += 1; + + mpConvergenceAcceleratorLeft->FinalizeNonLinearIteration(); + mpConvergenceAcceleratorRight->FinalizeNonLinearIteration(); + + KRATOS_CATCH( "" ); + } + + /** + * @brief Save the current step Jacobian + * This method saves the current step Jacobian as previous step Jacobian for the next time step iteration + */ + void FinalizeSolutionStep() override + { + KRATOS_TRY; + + mpConvergenceAcceleratorLeft->FinalizeSolutionStep(); + mpConvergenceAcceleratorRight->FinalizeSolutionStep(); + + KRATOS_CATCH( "" ); + } + + void Finalize() override + { + KRATOS_TRY; + + mpConvergenceAcceleratorLeft->Finalize(); + mpConvergenceAcceleratorRight->Finalize(); + + KRATOS_CATCH( "" ); + } + + void Clear() override + { + KRATOS_TRY; + + mpConvergenceAcceleratorLeft->Clear(); + mpConvergenceAcceleratorRight->Clear(); + + KRATOS_CATCH( "" ); + } + + bool IsBlockNewton() const override + { + return true; + } + + ///@} + ///@name Access + ///@{ + + + ///@} + ///@name Inquiry + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + + ///@} + ///@name Friends + ///@{ + + + ///@} +private: + ///@name Static Member Variables + ///@{ + + + ///@} + ///@name Member Variables + ///@{ + + double mInitialOmega; + + bool mFirstLeftCorrectionPerformed = false; // Indicates that the initial fixed point iteration has been already performed + bool mFirstRightCorrectionPerformed = false; // Indicates that the initial fixed point iteration has been already performed + unsigned int mConvergenceAcceleratorIteration = 0; // Convergence accelerator iteration counter + + MVQNPointerType mpConvergenceAcceleratorLeft; + MVQNPointerType mpConvergenceAcceleratorRight; + + typename BaseType::VectorPointerType mpUncorrectedForceVector; + typename BaseType::VectorPointerType mpUncorrectedDisplacementVector; + + + ///@} + ///@name Private Operators + ///@{ + + + ///@} + ///@name Private Operations + ///@{ + + + ///@} + ///@name Private Access + ///@{ + + + ///@} + ///@name Serialization + ///@{ + + + ///@} + ///@name Private Inquiry + ///@{ + + + ///@} + ///@name Un accessible methods + ///@{ + + + ///@} +}; /* Class IBQNMVQNConvergenceAccelerator */ + + +///@} +///@name Type Definitions +///@{ + +///@} +///@name Input and output +///@{ + +///@} + +} /* namespace Kratos.*/ + +#endif /* KRATOS_IBQN_MVQN_CONVERGENCE_ACCELERATOR defined */ diff --git a/applications/FSIApplication/custom_utilities/mvqn_convergence_accelerator.hpp b/applications/FSIApplication/custom_utilities/mvqn_convergence_accelerator.hpp index 46cfa81fa3fc..3c6bcdf5d408 100644 --- a/applications/FSIApplication/custom_utilities/mvqn_convergence_accelerator.hpp +++ b/applications/FSIApplication/custom_utilities/mvqn_convergence_accelerator.hpp @@ -21,9 +21,10 @@ #include "includes/ublas_interface.h" #include "solving_strategies/convergence_accelerators/convergence_accelerator.h" #include "utilities/svd_utils.h" -#include "utilities/math_utils.h" +#include "utilities/parallel_utilities.h" // Application includes +#include "ibqn_mvqn_convergence_accelerator.h" namespace Kratos { @@ -63,13 +64,11 @@ class MVQNFullJacobianConvergenceAccelerator: public ConvergenceAccelerator BaseType; typedef typename BaseType::Pointer BaseTypePointer; - typedef typename BaseType::VectorType VectorType; - typedef typename BaseType::VectorPointerType VectorPointerType; + typedef typename BaseType::DenseVectorType VectorType; + typedef typename BaseType::DenseVectorPointerType VectorPointerType; - typedef typename BaseType::MatrixType MatrixType; - typedef typename BaseType::MatrixPointerType MatrixPointerType; - - typedef typename TDenseSpace::MatrixType DenseMatrixType; + typedef typename BaseType::DenseMatrixType MatrixType; + typedef typename BaseType::DenseMatrixPointerType MatrixPointerType; ///@} ///@name Life Cycle @@ -77,49 +76,48 @@ class MVQNFullJacobianConvergenceAccelerator: public ConvergenceAccelerator; + + ///@} +protected: + ///@name Protected Operations + ///@{ + void UpdateInverseJacobianApproximation( + const VectorType& rResidualVector, + const VectorType& rIterationGuess) + { VectorPointerType pAuxResidualVector(new VectorType(rResidualVector)); VectorPointerType pAuxIterationGuess(new VectorType(rIterationGuess)); std::swap(mpResidualVector_1, pAuxResidualVector); std::swap(mpIterationValue_1, pAuxIterationGuess); if (mConvergenceAcceleratorIteration == 0) { - if (mConvergenceAcceleratorFirstCorrectionPerformed == false) { - // The very first correction of the problem is done with a fixed point iteration - TSparseSpace::UnaliasedAdd(rIterationGuess, mOmega_0, *mpResidualVector_1); - - // Initialize the Jacobian approximation matrix as minus the diagonal matrix - // Note that this is exclusively done in the very fist iteration - MatrixPointerType p_new_jac_n = Kratos::make_shared(mProblemSize,mProblemSize); - (*p_new_jac_n) = -1.0 * IdentityMatrix(mProblemSize,mProblemSize); - std::swap(p_new_jac_n,mpJac_n); - - mConvergenceAcceleratorFirstCorrectionPerformed = true; + if (!mJacobiansAreInitialized) { + // Initialize the problem size with the first residual + mProblemSize = TSparseSpace::Size(rResidualVector); + + // Initialize the Jacobian matrices + // This method already considers if the current MVQN accelerator is applied in a block Newton iteration + InitializeJacobianMatrices(); + mJacobiansAreInitialized = true; } else { - // Fist step correction is done with the previous step Jacobian - VectorType AuxVec(mProblemSize); - TSparseSpace::Mult(*mpJac_n, *mpResidualVector_1, AuxVec); - TSparseSpace::UnaliasedAdd(rIterationGuess, -1.0, AuxVec); + // Set as current iteration Jacobian the previous step one + // This is required since the first iteration needs to be performed with the previous step Jacobian + MatrixPointerType p_aux_jac_n = Kratos::make_shared(*mpJac_n); + std::swap(p_aux_jac_n, mpJac_k1); } } else { + // Store current observation information if (mConvergenceAcceleratorIteration == 1) { - // Resize the observation matrices in accordance to the problem size - MatrixPointerType pNewObsMatrixV = MatrixPointerType(new MatrixType(mProblemSize, 1)); - MatrixPointerType pNewObsMatrixW = MatrixPointerType(new MatrixType(mProblemSize, 1)); - - std::swap(mpObsMatrixV,pNewObsMatrixV); - std::swap(mpObsMatrixW,pNewObsMatrixW); - - // First observation matrices fill - for (unsigned int i = 0; i < mProblemSize; i++) - { - (*mpObsMatrixV)(i,0) = (*mpResidualVector_1)(i) - (*mpResidualVector_0)(i); - (*mpObsMatrixW)(i,0) = (*mpIterationValue_1)(i) - (*mpIterationValue_0)(i); - } + // Resize and initalize the observation matrices + InitializeDataColumns(); } else { // Reshape the existent observation matrices const std::size_t n_old_cols = mpObsMatrixV->size2(); - if (n_old_cols < mProblemSize){ - this->AppendDataColumns(); + if (n_old_cols < mProblemSize) { + AppendDataColumns(); } else { - this->DropAndAppendDataColumns(); + DropAndAppendDataColumns(); } - } // Compute the jacobian approximation std::size_t data_cols = mpObsMatrixV->size2(); - DenseMatrixType aux2(data_cols, data_cols); + MatrixType aux2(data_cols, data_cols); noalias(aux2) = prod(trans(*mpObsMatrixV),*mpObsMatrixV); // Perform the observation matrix V Singular Value Decomposition (SVD) such that // matrix V (m x n) is equal to the SVD matrices product V = u_svd * w_svd * v_svd - DenseMatrixType u_svd; // Orthogonal matrix (m x m) - DenseMatrixType w_svd; // Rectangular diagonal matrix (m x n) - DenseMatrixType v_svd; // Orthogonal matrix (n x n) + MatrixType u_svd; // Orthogonal matrix (m x m) + MatrixType w_svd; // Rectangular diagonal matrix (m x n) + MatrixType v_svd; // Orthogonal matrix (n x n) std::string svd_type = "Jacobi"; // SVD decomposition type double svd_rel_tol = 1.0e-6; // Relative tolerance of the SVD decomposition (it will be multiplied by the input matrix norm) SVDUtils::SingularValueDecomposition(aux2, u_svd, w_svd, v_svd, svd_type, svd_rel_tol); @@ -246,7 +299,7 @@ class MVQNFullJacobianConvergenceAccelerator: public ConvergenceAcceleratorDropLastDataColumn(); // Update the number of columns @@ -254,95 +307,80 @@ class MVQNFullJacobianConvergenceAccelerator: public ConvergenceAccelerator::SingularValueDecomposition(aux2, u_svd, w_svd, v_svd, svd_type, svd_rel_tol); } - // Perform the matrix inversion - double det_aux2; - MatrixType aux2inv(data_cols, data_cols); - MathUtils::InvertMatrix(aux2, aux2inv, det_aux2, -1.0e-15); - KRATOS_WARNING_IF("MVQNFullJacobianConvergenceAccelerator", std::pow(max_eig_V,2) / std::pow(min_eig_V,2) < std::pow(mAbsCutOff,2)) - << "Inverted matrix determinant is close to be singular" << std::endl; + // Compute the matrix pseudo-inverse + // Note that we take advantage of the fact that the matrix is always squared + MatrixType aux2_inv = ZeroMatrix(data_cols, data_cols); + for (std::size_t i = 0; i < data_cols; ++i) { + for (std::size_t j = 0; j < data_cols; ++j) { + const double aux = v_svd(j,i) / w_svd(j,j); + for (std::size_t k = 0; k < data_cols; ++k) { + aux2_inv(i,k) += aux * u_svd(k,j); + } + } + } // Compute the current inverse Jacobian approximation MatrixType aux1(mProblemSize, data_cols); MatrixType aux3(mProblemSize, data_cols); noalias(aux1) = *mpObsMatrixW - prod(*mpJac_n,*mpObsMatrixV); - noalias(aux3) = prod(aux1,aux2inv); + noalias(aux3) = prod(aux1,aux2_inv); - MatrixPointerType pJac_k1 = MatrixPointerType(new MatrixType(mProblemSize, mProblemSize)); - std::swap(mpJac_k1,pJac_k1); - noalias(*mpJac_k1) = *mpJac_n + prod(aux3,trans(*mpObsMatrixV)); + MatrixPointerType p_aux_jac_k1 = MatrixPointerType(new MatrixType(*mpJac_n + prod(aux3,trans(*mpObsMatrixV)))); + std::swap(mpJac_k1, p_aux_jac_k1); + } + } + void UpdateIterationGuess(VectorType& rIterationGuess) + { + if (mConvergenceAcceleratorFirstCorrectionPerformed == false) { + // The very first correction of the problem is done with a fixed point iteration + TSparseSpace::UnaliasedAdd(rIterationGuess, mOmega_0, *mpResidualVector_1); + mConvergenceAcceleratorFirstCorrectionPerformed = true; + } else { // Perform the correction + // In the first iterations, the correction is performed with previous step Jacobian (stored in mpJac_k1) + // In the subsequent iterations, the previous step Jacobian is updated with the observation matrices VectorType AuxVec(mProblemSize); TSparseSpace::Mult(*mpJac_k1, *mpResidualVector_1, AuxVec); TSparseSpace::UnaliasedAdd(rIterationGuess, -1.0, AuxVec); } - - KRATOS_CATCH( "" ); } - /** - * @brief Do the MVQN variables update - * Updates the MVQN iteration variables for the next non-linear iteration - */ - void FinalizeNonLinearIteration() override - { - KRATOS_TRY; - - // Variables update - mpIterationValue_0 = mpIterationValue_1; - mpResidualVector_0 = mpResidualVector_1; - mConvergenceAcceleratorIteration += 1; + ///@} + ///@name Protected Access + ///@{ - KRATOS_CATCH( "" ); + std::size_t GetProblemSize() const override + { + return mProblemSize; } - /** - * @brief Save the current step Jacobian - * This method saves the current step Jacobian as previous step Jacobian for the next time step iteration - */ - void FinalizeSolutionStep() override + MatrixPointerType pGetInverseJacobianApproximation() override { - KRATOS_TRY; - - // Update previous time step Jacobian as the last iteration Jacobian. - // Note that it is required to check if the last iteration Jacobian exists. It exist a corner case (if the - // very fist time step only requires the preliminary fixed point relaxation iteration to converge the - // previous iteration Jacobian is not needed) that might set a nullptr as previous step Jacobian. - if (mpJac_k1) { - mpJac_n = mpJac_k1; - } - - KRATOS_CATCH( "" ); + return mpJac_k1; } ///@} - ///@name Access - ///@{ - - ///@} - ///@name Inquiry +private: + ///@name Static Member Variables ///@{ - ///@} - ///@name Input and output - ///@{ ///@} - ///@name Friends - ///@{ - -private: - - ///@name Static Member Variables + ///@name Member Variables ///@{ - double mOmega_0; // Relaxation factor for the initial fixed point iteration - double mAbsCutOff; // Tolerance for the absolute cut-off criterion - unsigned int mProblemSize; // Residual to minimize size - unsigned int mConvergenceAcceleratorIteration; // Convergence accelerator iteration counter - bool mConvergenceAcceleratorFirstCorrectionPerformed; // Indicates that the initial fixed point iteration has been already performed + double mOmega_0; // Relaxation factor for the initial fixed point iteration + double mAbsCutOff; // Tolerance for the absolute cut-off criterion + bool mUsedInBlockNewtonEquations; // Indicates if the current MVQN is to be used in the interface block Newton equations + unsigned int mProblemSize = 0; // Residual to minimize size + unsigned int mConvergenceAcceleratorIteration = 0; // Convergence accelerator iteration counter + bool mJacobiansAreInitialized = false; // Indicates that the Jacobian matrices have been already initialized + bool mConvergenceAcceleratorFirstCorrectionPerformed = false; // Indicates that the initial fixed point iteration has been already performed VectorPointerType mpResidualVector_0; // Previous iteration residual vector VectorPointerType mpResidualVector_1; // Current iteration residual vector @@ -354,14 +392,47 @@ class MVQNFullJacobianConvergenceAccelerator: public ConvergenceAccelerator(mProblemSize,mProblemSize); + (*p_new_jac_n) = ZeroMatrix(mProblemSize,mProblemSize); + std::swap(p_new_jac_n,mpJac_n); + + // Initialize the current Jacobian approximation to a zero matrix + // Note that this is only required for the Interface Block Newton algorithm + MatrixPointerType p_new_jac_k1 = Kratos::make_shared(mProblemSize,mProblemSize); + (*p_new_jac_k1) = ZeroMatrix(mProblemSize,mProblemSize); + std::swap(p_new_jac_k1, mpJac_k1); + } else { + // Initialize the previous step Jacobian approximation to minus the diagonal matrix + MatrixPointerType p_new_jac_n = Kratos::make_shared(mProblemSize,mProblemSize); + (*p_new_jac_n) = -1.0 * IdentityMatrix(mProblemSize,mProblemSize); + std::swap(p_new_jac_n,mpJac_n); + } + } + + void InitializeDataColumns() + { + // Resize the observation matrices in accordance to the problem size + MatrixPointerType p_aux_V = MatrixPointerType(new MatrixType(mProblemSize, 1)); + MatrixPointerType p_aux_W = MatrixPointerType(new MatrixType(mProblemSize, 1)); + std::swap(mpObsMatrixV, p_aux_V); + std::swap(mpObsMatrixW, p_aux_W); + + // First observation matrices fill + IndexPartition(mProblemSize).for_each([&](unsigned int I){ + (*mpObsMatrixV)(I,0) = (*mpResidualVector_1)(I) - (*mpResidualVector_0)(I); + (*mpObsMatrixW)(I,0) = (*mpIterationValue_1)(I) - (*mpIterationValue_0)(I); + }); + } + /** * @brief Append the new data to the observation matrices * This function appends the new data to both observation matrices @@ -374,18 +445,18 @@ class MVQNFullJacobianConvergenceAccelerator: public ConvergenceAccelerator(mProblemSize, n_old_cols + 1); // Recover the previous iterations information - for (unsigned int i = 0; i < mProblemSize; i++){ + IndexPartition(mProblemSize).for_each([&](unsigned int I){ for (unsigned int j = 0; j < n_old_cols; j++){ - (*p_new_V)(i,j) = (*mpObsMatrixV)(i,j); - (*p_new_W)(i,j) = (*mpObsMatrixW)(i,j); + (*p_new_V)(I,j) = (*mpObsMatrixV)(I,j); + (*p_new_W)(I,j) = (*mpObsMatrixW)(I,j); } - } + }); // Fill the attached column with the current iteration information - for (unsigned int i = 0; i < mProblemSize; i++){ - (*p_new_V)(i, n_old_cols) = (*mpResidualVector_1)(i) - (*mpResidualVector_0)(i); - (*p_new_W)(i, n_old_cols) = (*mpIterationValue_1)(i) - (*mpIterationValue_0)(i); - } + IndexPartition(mProblemSize).for_each([&](unsigned int I){ + (*p_new_V)(I, n_old_cols) = (*mpResidualVector_1)(I) - (*mpResidualVector_0)(I); + (*p_new_W)(I, n_old_cols) = (*mpIterationValue_1)(I) - (*mpIterationValue_0)(I); + }); std::swap(mpObsMatrixV,p_new_V); std::swap(mpObsMatrixW,p_new_W); @@ -402,18 +473,18 @@ class MVQNFullJacobianConvergenceAccelerator: public ConvergenceAccelerator(mProblemSize, mProblemSize); // Drop the oldest column and reorder data - for (unsigned int i = 0; i < mProblemSize; i++){ + IndexPartition(mProblemSize).for_each([&](unsigned int I){ for (unsigned int j = 0; j < (mProblemSize-1); j++){ - (*p_new_V)(i,j) = (*mpObsMatrixV)(i,j+1); - (*p_new_W)(i,j) = (*mpObsMatrixW)(i,j+1); + (*p_new_V)(I,j) = (*mpObsMatrixV)(I,j+1); + (*p_new_W)(I,j) = (*mpObsMatrixW)(I,j+1); } - } + }); // Fill the last observation matrices column - for (unsigned int i = 0; i < mProblemSize; i++){ - (*p_new_V)(i, mProblemSize-1) = (*mpResidualVector_1)(i) - (*mpResidualVector_0)(i); - (*p_new_W)(i, mProblemSize-1) = (*mpIterationValue_1)(i) - (*mpIterationValue_0)(i); - } + IndexPartition(mProblemSize).for_each([&](unsigned int I){ + (*p_new_V)(I, mProblemSize-1) = (*mpResidualVector_1)(I) - (*mpResidualVector_0)(I); + (*p_new_W)(I, mProblemSize-1) = (*mpIterationValue_1)(I) - (*mpIterationValue_0)(I); + }); std::swap(mpObsMatrixV,p_new_V); std::swap(mpObsMatrixW,p_new_W); @@ -431,12 +502,12 @@ class MVQNFullJacobianConvergenceAccelerator: public ConvergenceAccelerator(mProblemSize, n_cols); // Drop the last column - for (std::size_t i_row = 0; i_row < mProblemSize; ++i_row){ + IndexPartition(mProblemSize).for_each([&](unsigned int IRow){ for (std::size_t i_col = 0; i_col < n_cols; ++i_col){ - (*p_aux_V)(i_row, i_col) = (*mpObsMatrixV)(i_row, i_col); - (*p_aux_W)(i_row, i_col) = (*mpObsMatrixW)(i_row, i_col); + (*p_aux_V)(IRow, i_col) = (*mpObsMatrixV)(IRow, i_col); + (*p_aux_W)(IRow, i_col) = (*mpObsMatrixW)(IRow, i_col); } - } + }); // Set the member observation matrices pointers std::swap(mpObsMatrixV,p_aux_V); diff --git a/applications/FSIApplication/custom_utilities/mvqn_recursive_convergence_accelerator.hpp b/applications/FSIApplication/custom_utilities/mvqn_recursive_convergence_accelerator.hpp index 933a19714157..2ee6996a3c9e 100644 --- a/applications/FSIApplication/custom_utilities/mvqn_recursive_convergence_accelerator.hpp +++ b/applications/FSIApplication/custom_utilities/mvqn_recursive_convergence_accelerator.hpp @@ -434,10 +434,11 @@ class MVQNRecursiveJacobianConvergenceAccelerator: public ConvergenceAccelerator { Parameters mvqn_recursive_default_parameters(R"( { - "solver_type" : "MVQN_recursive", - "w_0" : 0.825, - "buffer_size" : 10, - "abs_cut_off_tol" : 1e-8 + "solver_type" : "MVQN_recursive", + "w_0" : 0.825, + "buffer_size" : 10, + "abs_cut_off_tol" : 1e-8, + "interface_block_newton" : false } )"); diff --git a/applications/FSIApplication/custom_utilities/partitioned_fsi_utilities.hpp b/applications/FSIApplication/custom_utilities/partitioned_fsi_utilities.hpp index 36de4948cf2b..afe6b9a0a481 100644 --- a/applications/FSIApplication/custom_utilities/partitioned_fsi_utilities.hpp +++ b/applications/FSIApplication/custom_utilities/partitioned_fsi_utilities.hpp @@ -31,6 +31,7 @@ #include "includes/ublas_interface.h" #include "utilities/binbased_fast_point_locator.h" #include "utilities/math_utils.h" +#include "utilities/normal_calculation_utils.h" #include "utilities/openmp_utils.h" #include "utilities/variable_utils.h" @@ -102,28 +103,38 @@ class PartitionedFSIUtilities /*@{ */ /** - * @brief Create a coupling element based skin object - * This method creates an element based skin model part by + * @brief Create a coupling condition-based skin object + * This method creates an condition-based skin model part by * copying the conditions of a given skin model part * @param rOriginInterfaceModelPart Origin skin model part to copy the conditions from - * @param rDestinationInterfaceModelPart Empty destination modelpart to create the skin elements + * @param rDestinationInterfaceModelPart Empty destination modelpart to create the skin nodes and conditions */ - void CreateCouplingElementBasedSkin( + void CreateCouplingSkin( const ModelPart &rOriginInterfaceModelPart, ModelPart &rDestinationInterfaceModelPart) { // Check the origin interface model part - KRATOS_ERROR_IF(rOriginInterfaceModelPart.NumberOfNodes() == 0) << "Origin model part has no nodes." << std::endl; - KRATOS_ERROR_IF(rOriginInterfaceModelPart.NumberOfConditions() == 0) << "Origin model part has no conditions." << std::endl; + const auto& r_communicator = rOriginInterfaceModelPart.GetCommunicator(); + KRATOS_ERROR_IF(r_communicator.GlobalNumberOfNodes() == 0) << "Origin model part has no nodes." << std::endl; + KRATOS_ERROR_IF(r_communicator.GlobalNumberOfConditions() == 0) << "Origin model part has no conditions." << std::endl; // Check the destination interface model part KRATOS_ERROR_IF(rDestinationInterfaceModelPart.IsSubModelPart()) << "Destination model part must be a root model part." << std::endl; KRATOS_ERROR_IF(rDestinationInterfaceModelPart.NumberOfNodes() != 0) << "Destination interface model part should be empty. Current number of nodes: " << rDestinationInterfaceModelPart.NumberOfNodes() << std::endl; KRATOS_ERROR_IF(rDestinationInterfaceModelPart.NumberOfElements() != 0) << "Destination interface model part should be empty. Current number of elements: " << rDestinationInterfaceModelPart.NumberOfElements() << std::endl; + KRATOS_ERROR_IF(rDestinationInterfaceModelPart.NumberOfConditions() != 0) << "Destination interface model part should be empty. Current number of conditions: " << rDestinationInterfaceModelPart.NumberOfConditions() << std::endl; // Emulate the origin interface nodes in the coupling skin - for (const auto &r_node : rOriginInterfaceModelPart.Nodes()) { - rDestinationInterfaceModelPart.CreateNewNode(r_node.Id(), r_node); + // Note that if the origin model part is MPI parallel we copy the PARTITION_INDEX to the coupling skin mesh + if (rOriginInterfaceModelPart.IsDistributed()) { + for (const auto &r_node : rOriginInterfaceModelPart.Nodes()) { + auto p_new_node = rDestinationInterfaceModelPart.CreateNewNode(r_node.Id(), r_node); + p_new_node->FastGetSolutionStepValue(PARTITION_INDEX) = r_node.FastGetSolutionStepValue(PARTITION_INDEX); + } + } else { + for (const auto &r_node : rOriginInterfaceModelPart.Nodes()) { + rDestinationInterfaceModelPart.CreateNewNode(r_node.Id(), r_node); + } } // Create the new element based skin @@ -134,34 +145,8 @@ class PartitionedFSIUtilities nodes_vect.push_back(r_node.Id()); } - // Create the new skin element - rDestinationInterfaceModelPart.CreateNewElement(this->GetSkinElementName(), r_cond.Id(), nodes_vect, r_cond.pGetProperties()); - } - } - - /** - * @brief Creates an element based skin - * For a modelpart defining the skin using conditions, this method - * copies such skin to the elements of an auxiliar model part. Note - * that the same geometry is used so the nodes of the auxiliar geometry - * are actually the ones in the origin modelpart. - * @param rOriginInterfaceModelPart - * @param rDestinationInterfaceModelPart - */ - void CopySkinToElements( - const ModelPart& rOriginInterfaceModelPart, - ModelPart& rDestinationInterfaceModelPart) - { - // Add the origin interface nodes to the destination interface model part - rDestinationInterfaceModelPart.AddNodes( - rOriginInterfaceModelPart.NodesBegin(), - rOriginInterfaceModelPart.NodesEnd()); - - // Create new elements emulating the condition based interface - for (std::size_t i_cond = 0; i_cond < rOriginInterfaceModelPart.NumberOfConditions(); ++i_cond) { - const auto &it_cond = rOriginInterfaceModelPart.ConditionsBegin() + i_cond; - auto p_elem = Kratos::make_intrusive(it_cond->Id(), it_cond->pGetGeometry()); - rDestinationInterfaceModelPart.AddElement(p_elem); + // Create the new condition element + rDestinationInterfaceModelPart.CreateNewCondition(this->GetSkinConditionName(), r_cond.Id(), nodes_vect, r_cond.pGetProperties()); } } @@ -622,7 +607,7 @@ class PartitionedFSIUtilities // If the structure skin is found, interpolate the POSITIVE_FACE_PRESSURE from the PRESSURE if (found) { const auto &r_geom = p_elem->GetGeometry(); - double &r_pres = it_node->FastGetSolutionStepValue(PRESSURE); + double &r_pres = it_node->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE); r_pres = 0.0; for (unsigned int i_node = 0; i_node < r_geom.PointsNumber(); ++i_node) { r_pres += N[i_node] * r_geom[i_node].FastGetSolutionStepValue(PRESSURE); @@ -631,6 +616,64 @@ class PartitionedFSIUtilities } } + void CalculateTractionFromPressureValues( + ModelPart& rModelPart, + const Variable& rPressureVariable, + const Variable>& rTractionVariable, + const bool SwapTractionSign) + { + // Update the nodal normals + NormalCalculationUtils().CalculateOnSimplex(rModelPart); + + // Set the nodal traction modulus calculation function + std::function)> traction_modulus_func; + if (SwapTractionSign) { + traction_modulus_func = [](const double PosPressure, const array_1d& rNormal){return - PosPressure / norm_2(rNormal);}; + } else { + traction_modulus_func = [](const double PosPressure, const array_1d& rNormal){return PosPressure / norm_2(rNormal);}; + } + + // Calculate the tractions from the pressure values + block_for_each(rModelPart.Nodes(), [&](Node<3>& rNode){ + const array_1d& r_normal = rNode.FastGetSolutionStepValue(NORMAL); + const double p_pos = rNode.FastGetSolutionStepValue(rPressureVariable); + noalias(rNode.FastGetSolutionStepValue(rTractionVariable)) = traction_modulus_func(p_pos, r_normal) * r_normal; + }); + + // Synchronize values among processes + rModelPart.GetCommunicator().SynchronizeVariable(rTractionVariable); + } + + void CalculateTractionFromPressureValues( + ModelPart& rModelPart, + const Variable& rPositivePressureVariable, + const Variable& rNegativePressureVariable, + const Variable>& rTractionVariable, + const bool SwapTractionSign) + { + // Update the nodal normals + NormalCalculationUtils().CalculateOnSimplex(rModelPart); + + // Set the nodal traction modulus calculation function + std::function)> traction_modulus_func; + if (SwapTractionSign) { + traction_modulus_func = [](const double PosPressure, const double NegPressure, const array_1d& rNormal){return (NegPressure - PosPressure) / norm_2(rNormal);}; + } else { + traction_modulus_func = [](const double PosPressure, const double NegPressure, const array_1d& rNormal){return (PosPressure - NegPressure) / norm_2(rNormal);}; + } + + // Calculate the tractions from the pressure values + block_for_each(rModelPart.Nodes(), [&](Node<3>& rNode){ + const array_1d& r_normal = rNode.FastGetSolutionStepValue(NORMAL); + const double p_pos = rNode.FastGetSolutionStepValue(rPositivePressureVariable); + const double p_neg = rNode.FastGetSolutionStepValue(rNegativePressureVariable); + noalias(rNode.FastGetSolutionStepValue(rTractionVariable)) = traction_modulus_func(p_pos, p_neg, r_normal) * r_normal; + }); + + // Synchronize values among processes + rModelPart.GetCommunicator().SynchronizeVariable(rTractionVariable); + } + /*@} */ protected: /**@name Protected static Member Variables */ @@ -666,6 +709,20 @@ class PartitionedFSIUtilities return element_name; } + /** + * @brief Get the skin condition name + * Auxiliary method that returns the auxiliary embedded skin condition type name + * @return std::string Condition type registering name + */ + std::string GetSkinConditionName() + { + if (TDim == 2) { + return "LineCondition2D2N"; + } else { + return "SurfaceCondition3D3N"; + } + } + /** * This function computes the nodal error of a vector magnitude in a consistent manner. * The error is defined as the integral over the interface of a tests function times @@ -754,7 +811,7 @@ class PartitionedFSIUtilities auto &r_error_storage = it_node->FastGetSolutionStepValue(rErrorStorageVariable); const auto &value_origin = it_node->FastGetSolutionStepValue(rOriginalVariable); const auto &value_modified = it_node->FastGetSolutionStepValue(rModifiedVariable); - r_error_storage = value_origin - value_modified; + r_error_storage = value_modified - value_origin; } } diff --git a/applications/FSIApplication/python_scripts/convergence_accelerator_factory.py b/applications/FSIApplication/python_scripts/convergence_accelerator_factory.py index 630c4637f1f8..c39f20f54e1b 100644 --- a/applications/FSIApplication/python_scripts/convergence_accelerator_factory.py +++ b/applications/FSIApplication/python_scripts/convergence_accelerator_factory.py @@ -34,6 +34,9 @@ def CreateConvergenceAccelerator(configuration): elif(convergence_accelerator_type == "MVQN_recursive"): return KratosFSI.MVQNRecursiveJacobianConvergenceAccelerator(configuration) + elif(convergence_accelerator_type == "IBQN_MVQN"): + return KratosFSI.IBQNMVQNConvergenceAccelerator(configuration) + else: raise Exception("Convergence accelerator not found. Asking for : " + convergence_accelerator_type) diff --git a/applications/FSIApplication/python_scripts/fsi_coupling_interface.py b/applications/FSIApplication/python_scripts/fsi_coupling_interface.py index ba3416b8aaed..9b296604ec63 100644 --- a/applications/FSIApplication/python_scripts/fsi_coupling_interface.py +++ b/applications/FSIApplication/python_scripts/fsi_coupling_interface.py @@ -1,12 +1,12 @@ -from __future__ import print_function, absolute_import, division # makes KratosMultiphysics backward compatible with python 2.6 and 2.7 - # Importing the Kratos Library import KratosMultiphysics # Import applications import KratosMultiphysics.FSIApplication as KratosFSI +if KratosMultiphysics.ParallelEnvironment.GetDefaultDataCommunicator().IsDistributed(): + import KratosMultiphysics.TrilinosApplication as KratosTrilinos -class FSICouplingInterface(): +class FSICouplingInterface: def __ValidateSettings(self, settings): default_settings = KratosMultiphysics.Parameters(""" @@ -14,7 +14,8 @@ def __ValidateSettings(self, settings): "model_part_name": "", "parent_model_part_name": "", "input_variable_list": [], - "output_variable_list": [] + "output_variable_list": [], + "auxiliary_variable_list": [] }""") settings.ValidateAndAssignDefaults(default_settings) @@ -41,6 +42,50 @@ def __init__(self, model, settings, convergence_accelerator = None): self.parent_model_part_name = settings["parent_model_part_name"].GetString() self.input_variable_list = settings["input_variable_list"] self.output_variable_list = settings["output_variable_list"] + self.auxiliary_variable_list = settings["auxiliary_variable_list"] + + # Check the variables list sizes + n_input_vars = self.input_variable_list.size() + if n_input_vars != 1: + err_msg = "\'input_variable_list\' size is {0}. Expected 1.".format(n_input_vars) + raise Exception(err_msg) + n_output_vars = self.output_variable_list.size() + if (n_output_vars == 0) or (n_output_vars > 2): + err_msg = "\'output_variable_list\' size is {0}. Expected 1 or 2.".format(n_output_vars) + raise Exception(err_msg) + + # Check and get the output variable(s) data type + aux_list = [] + for variable in self.output_variable_list: + if KratosMultiphysics.KratosGlobals.Kernel.HasDoubleVariable(variable.GetString()): + aux_list.append(True) + elif KratosMultiphysics.KratosGlobals.Kernel.HasArrayVariable(variable.GetString()): + aux_list.append(False) + else: + aux_list.append(None) + break + + if aux_list.count(None) != 0: + err_msg = "Non-expected variable type in \'output_variable_list\'. Only scalar and array variables are supported." + raise Exception(err_msg) + + self.scalar_output = None + if aux_list.count(True) == n_output_vars: + self.scalar_output = True + elif aux_list.count(False) == n_output_vars: + self.scalar_output = False + else: + err_msg = "Scalar and array variable types are mixed in the \'output_variable_list\'." + raise Exception(err_msg) + + def SetConvergenceAccelerator(self, convergence_accelerator): + """Set the provided convergence accelerator to the current FSI coupling interface + + This function sets the convergence accelerator of the current FSI coupling interface + This auxiliary method is understood to set the convergence accelerator in those situations + in which its constructor requires the FSI coupling interface model part to be set (e.g. MPI) + """ + self.convergence_accelerator = convergence_accelerator def GetInterfaceModelPart(self): if not hasattr(self, '_fsi_interface_model_part'): @@ -50,61 +95,155 @@ def GetInterfaceModelPart(self): def GetFatherModelPart(self): return self.model.GetModelPart(self.parent_model_part_name) - def Update(self): + def ComputeResidualVector(self): # Check that the output variable that defines the residual is unique and get it if (self.output_variable_list.size() == 1): output_variable_name = self.output_variable_list[0].GetString() output_variable = KratosMultiphysics.KratosGlobals.GetVariable(output_variable_name) else: - err_msg = "Update() can only be performed with a unique output variable.\n" - err_msg = "Number of variables in \'output_variable_list\' is " + int(self.output_variable_list.size()) + err_msg = "ComputeResidualVector() can only be performed with a unique output variable.\n" + err_msg += "Number of variables in \'output_variable_list\' is " + int(self.output_variable_list.size()) raise Exception(err_msg) # Get the output variable from the father model part # Note that this are the current non-linear iteration unrelaxed values (\tilde{u}^{k+1}) + # These values will be used below to calculate the interface residual vector self.GetValuesFromFatherModelPart(output_variable) # Save the previously existent RELAXED_DISPLACEMENT in OLD_RELAXED_DISPLACEMENT before doing the update - for node in self.GetInterfaceModelPart().Nodes: - relaxed_disp = node.GetSolutionStepValue(KratosMultiphysics.RELAXED_DISPLACEMENT) - node.SetSolutionStepValue(KratosMultiphysics.OLD_RELAXED_DISPLACEMENT, relaxed_disp) + # These values will be used below to calculate the interface residual vector (u^{k}) + KratosMultiphysics.VariableUtils().CopyVariable( + self._relaxed_variable, + self._old_relaxed_variable, + self.GetInterfaceModelPart().Nodes) - # Get the interface residual size - residual_size = self._get_partitioned_fsi_utilities().GetInterfaceResidualSize(self.GetInterfaceModelPart()) + # Compute the current non-linear iteration interface residual using the output variable + # Note that the residual is computed as r^{k+1} = \tilde{u}^{k+1} - u^{k} + self._output_variable_residual_vector = self._get_partitioned_fsi_utilities().SetUpInterfaceVector(self.GetInterfaceModelPart()) + self._get_partitioned_fsi_utilities().ComputeInterfaceResidualVector( + self.GetInterfaceModelPart(), + self._old_relaxed_variable, + output_variable, + self._residual_variable, + self._output_variable_residual_vector, + "nodal", + KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM) + # Return the current interface residual norm + return self.GetInterfaceModelPart().ProcessInfo[KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM] + + def Update(self): # Set and fill the iteration value vector with the previous non-linear iteration relaxed values (u^{k}) - iteration_value_vector = KratosMultiphysics.Vector(residual_size) + iteration_value_vector = self._get_partitioned_fsi_utilities().SetUpInterfaceVector(self.GetInterfaceModelPart()) self._get_partitioned_fsi_utilities().InitializeInterfaceVector( self.GetInterfaceModelPart(), - KratosMultiphysics.OLD_RELAXED_DISPLACEMENT, + self._old_relaxed_variable, iteration_value_vector) - # Compute the current non-linear iteration interface residual using the output variable - # Note that the residual is computed as r^{k+1} = \tilde{u}^{k+1} - u^{k} - output_variable_residual_vector = KratosMultiphysics.Vector(residual_size) - self._get_partitioned_fsi_utilities().ComputeInterfaceResidualVector( + # Compute the convergence accelerator correction + self._get_convergence_accelerator().UpdateSolution(self._output_variable_residual_vector, iteration_value_vector) + + # Apply the corrected solution to the FSI coupling interface nodes + self._get_partitioned_fsi_utilities().UpdateInterfaceValues( + self.GetInterfaceModelPart(), + self._relaxed_variable, + iteration_value_vector) + + def UpdateDisplacement(self): + # Set and fill the iteration value vector with the previous non-linear iteration relaxed values (u^{k}) + iteration_value_vector = self._get_partitioned_fsi_utilities().SetUpInterfaceVector(self.GetInterfaceModelPart()) + self._get_partitioned_fsi_utilities().InitializeInterfaceVector( + self.GetInterfaceModelPart(), + self._relaxed_variable, + iteration_value_vector) + + # Check that the output variable that defines the residual is unique and get it (i.e. DISPLACEMENT) + if (self.output_variable_list.size() == 1): + output_variable_name = self.output_variable_list[0].GetString() + output_variable = KratosMultiphysics.KratosGlobals.GetVariable(output_variable_name) + else: + err_msg = "ComputeResidualVector() can only be performed with a unique output variable.\n" + err_msg += "Number of variables in \'output_variable_list\' is " + int(self.output_variable_list.size()) + raise Exception(err_msg) + + # Get the output variable from the father model part + # Note that this are the current non-linear iteration unrelaxed values (\tilde{u}^{k+1}) + self.GetValuesFromFatherModelPart(output_variable) + + # Set and fill the displacement value vector with the current non-linear iteration values (\tilde{u}^{k+1}) + # Note that these are the current uncorrected displacement obtained with the previously corrected load + iteration_value_u_vector = self._get_partitioned_fsi_utilities().SetUpInterfaceVector(self.GetInterfaceModelPart()) + self._get_partitioned_fsi_utilities().InitializeInterfaceVector( self.GetInterfaceModelPart(), output_variable, - KratosMultiphysics.OLD_RELAXED_DISPLACEMENT, - KratosMultiphysics.FSI_INTERFACE_RESIDUAL, - output_variable_residual_vector, - "nodal", - KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM) + iteration_value_u_vector) + + # Set and fill the traction value vector with the current non-linear iteration values (f^{k+1}) + # Note that these are the values that were employed to obtain the current displacements + iteration_value_f_vector = self._get_partitioned_fsi_utilities().SetUpInterfaceVector(self.GetInterfaceModelPart()) + self._get_partitioned_fsi_utilities().InitializeInterfaceVector( + self.GetInterfaceModelPart(), + self._traction_relaxed_variable, + iteration_value_f_vector) # Compute the convergence accelerator correction - self._get_convergence_accelerator().UpdateSolution(output_variable_residual_vector, iteration_value_vector) + self._get_convergence_accelerator().UpdateSolutionRight( + iteration_value_f_vector, + iteration_value_u_vector, + iteration_value_vector) # Apply the corrected solution to the FSI coupling interface nodes self._get_partitioned_fsi_utilities().UpdateInterfaceValues( self.GetInterfaceModelPart(), - KratosMultiphysics.RELAXED_DISPLACEMENT, + self._relaxed_variable, iteration_value_vector) - # Return the current interface residual norm - return self.GetInterfaceModelPart().ProcessInfo[KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM] + def UpdateTraction(self): + # Set and fill the iteration value vector with the previous non-linear iteration relaxed values (f^{k}) + iteration_value_vector = self._get_partitioned_fsi_utilities().SetUpInterfaceVector(self.GetInterfaceModelPart()) + self._get_partitioned_fsi_utilities().InitializeInterfaceVector( + self.GetInterfaceModelPart(), + self._traction_relaxed_variable, + iteration_value_vector) + + # Set and fill the displacement value vector with the current non-linear iteration values (\tilde{f}^{k+1}) + if self.input_variable_list.size() == 1: + input_variable_name = self.input_variable_list[0].GetString() + input_variable = KratosMultiphysics.KratosGlobals.GetVariable(input_variable_name) + else: + err_msg = "Input variable list has more than one variable. One is expected for the IBQN update." + raise Exception(err_msg) + + iteration_value_f_vector = self._get_partitioned_fsi_utilities().SetUpInterfaceVector(self.GetInterfaceModelPart()) + self._get_partitioned_fsi_utilities().InitializeInterfaceVector( + self.GetInterfaceModelPart(), + input_variable, + iteration_value_f_vector) - def UpdatePosition(self): - KratosMultiphysics.VariableUtils().UpdateCurrentPosition(self.GetInterfaceModelPart().Nodes) + # Set and fill the traction value vector with the current non-linear iteration values (u^{k+1}) + # Note that these are the values that were employed to obtain the current tractions + iteration_value_u_vector = self._get_partitioned_fsi_utilities().SetUpInterfaceVector(self.GetInterfaceModelPart()) + self._get_partitioned_fsi_utilities().InitializeInterfaceVector( + self.GetInterfaceModelPart(), + self._relaxed_variable, + iteration_value_u_vector) + + # Compute the convergence accelerator correction + self._get_convergence_accelerator().UpdateSolutionLeft( + iteration_value_u_vector, + iteration_value_f_vector, + iteration_value_vector) + + # Apply the corrected solution to the FSI coupling interface nodes + self._get_partitioned_fsi_utilities().UpdateInterfaceValues( + self.GetInterfaceModelPart(), + self._traction_relaxed_variable, + iteration_value_vector) + + def UpdatePosition(self, update_variable = KratosMultiphysics.DISPLACEMENT): + KratosMultiphysics.VariableUtils().UpdateCurrentPosition( + self.GetInterfaceModelPart().Nodes, + update_variable) def GetValuesFromFatherModelPart(self, variable): buffer_step = 0 @@ -113,6 +252,8 @@ def GetValuesFromFatherModelPart(self, variable): self.GetFatherModelPart(), self.GetInterfaceModelPart(), buffer_step) + #TODO: Remove as soon as the CopyModelPartNodalVar synchronizes internally + self.GetInterfaceModelPart().GetCommunicator().SynchronizeVariable(variable) def TransferValuesToFatherModelPart(self, variable): buffer_step = 0 @@ -121,11 +262,17 @@ def TransferValuesToFatherModelPart(self, variable): self.GetInterfaceModelPart(), self.GetFatherModelPart(), buffer_step) + #TODO: Remove as soon as the CopyModelPartNodalVar synchronizes internally + self.GetFatherModelPart().GetCommunicator().SynchronizeVariable(variable) def _create_fsi_interface_model_part(self): # Add the FSI coupling interface to the model self._fsi_interface_model_part = self.model.CreateModelPart(self.model_part_name) + # Set required ProcessInfo data + domain_size = self.GetFatherModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + self._fsi_interface_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] = domain_size + # Add the required variables to the FSI coupling interface model part for variable_name in self.input_variable_list: input_variable = KratosMultiphysics.KratosGlobals.GetVariable(variable_name.GetString()) @@ -133,15 +280,53 @@ def _create_fsi_interface_model_part(self): for variable_name in self.output_variable_list: output_variable = KratosMultiphysics.KratosGlobals.GetVariable(variable_name.GetString()) self._fsi_interface_model_part.AddNodalSolutionStepVariable(output_variable) - self._fsi_interface_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.RELAXED_DISPLACEMENT) - self._fsi_interface_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.OLD_RELAXED_DISPLACEMENT) - self._fsi_interface_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.FSI_INTERFACE_RESIDUAL) + for variable_name in self.auxiliary_variable_list: + auxiliary_variable = KratosMultiphysics.KratosGlobals.GetVariable(variable_name.GetString()) + self._fsi_interface_model_part.AddNodalSolutionStepVariable(auxiliary_variable) + + # Add the variables required for the residual minimization + if self._get_convergence_accelerator() is not None: + # Get the required variables + if self.scalar_output: + self._relaxed_variable = KratosMultiphysics.RELAXED_SCALAR + self._old_relaxed_variable = KratosMultiphysics.OLD_RELAXED_SCALAR + self._residual_variable = KratosMultiphysics.SCALAR_INTERFACE_RESIDUAL + if self._get_convergence_accelerator().IsBlockNewton(): + self._traction_relaxed_variable = KratosMultiphysics.RELAXED_SCALAR_TRACTION + self._old_traction_relaxed_variable = KratosMultiphysics.OLD_RELAXED_SCALAR_TRACTION + self._traction_residual_variable = KratosMultiphysics.SCALAR_TRACTION_INTERFACE_RESIDUAL + else: + self._relaxed_variable = KratosMultiphysics.RELAXED_DISPLACEMENT + self._old_relaxed_variable = KratosMultiphysics.OLD_RELAXED_DISPLACEMENT + self._residual_variable = KratosMultiphysics.FSI_INTERFACE_RESIDUAL + if self._get_convergence_accelerator().IsBlockNewton(): + self._traction_relaxed_variable = KratosMultiphysics.RELAXED_TRACTION + self._old_traction_relaxed_variable = KratosMultiphysics.OLD_RELAXED_TRACTION + self._traction_residual_variable = KratosMultiphysics.TRACTION_INTERFACE_RESIDUAL + + # Add the required variables to the nodal database + self._fsi_interface_model_part.AddNodalSolutionStepVariable(self._relaxed_variable) + self._fsi_interface_model_part.AddNodalSolutionStepVariable(self._old_relaxed_variable) + self._fsi_interface_model_part.AddNodalSolutionStepVariable(self._residual_variable) + if self._get_convergence_accelerator().IsBlockNewton(): + self._fsi_interface_model_part.AddNodalSolutionStepVariable(self._traction_relaxed_variable) + self._fsi_interface_model_part.AddNodalSolutionStepVariable(self._old_traction_relaxed_variable) + self._fsi_interface_model_part.AddNodalSolutionStepVariable(self._traction_residual_variable) + + # If parallel, add the PARTITION_INDEX variable + if self.GetFatherModelPart().IsDistributed(): + self._fsi_interface_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PARTITION_INDEX) # Set the FSI coupling interface entities (nodes and elements) - self._get_partitioned_fsi_utilities().CreateCouplingElementBasedSkin( + self._get_partitioned_fsi_utilities().CreateCouplingSkin( self.GetFatherModelPart(), self._fsi_interface_model_part) + # Create the communication plan for the current coupling interface + # Note that we retrieve the fill communicator from the ParallelEnvironment so nothing would be done if non MPI + fill_communicator = KratosMultiphysics.ParallelEnvironment.CreateFillCommunicator(self._fsi_interface_model_part) + fill_communicator.Execute() + return self._fsi_interface_model_part def _get_convergence_accelerator(self): @@ -154,9 +339,30 @@ def _get_partitioned_fsi_utilities(self): def _create_partitioned_fsi_utilities(self): domain_size = self.GetFatherModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] - if domain_size == 2: - return KratosFSI.PartitionedFSIUtilitiesArray2D() - elif domain_size == 3: - return KratosFSI.PartitionedFSIUtilitiesArray3D() + if not self.GetFatherModelPart().IsDistributed(): + if domain_size == 2: + if self.scalar_output: + return KratosFSI.PartitionedFSIUtilitiesDouble2D() + else: + return KratosFSI.PartitionedFSIUtilitiesArray2D() + elif domain_size == 3: + if self.scalar_output: + return KratosFSI.PartitionedFSIUtilitiesDouble3D() + else: + return KratosFSI.PartitionedFSIUtilitiesArray3D() + else: + raise Exception("Domain size expected to be 2 or 3. Got " + str(self.domain_size)) else: - raise Exception("Domain size expected to be 2 or 3. Got " + str(self.domain_size)) + self._epetra_communicator = KratosTrilinos.CreateCommunicator() + if domain_size == 2: + if self.scalar_output: + return KratosTrilinos.TrilinosPartitionedFSIUtilitiesDouble2D(self._epetra_communicator) + else: + return KratosTrilinos.TrilinosPartitionedFSIUtilitiesArray2D(self._epetra_communicator) + elif domain_size == 3: + if self.scalar_output: + return KratosTrilinos.TrilinosPartitionedFSIUtilitiesDouble3D(self._epetra_communicator) + else: + return KratosTrilinos.TrilinosPartitionedFSIUtilitiesArray3D(self._epetra_communicator) + else: + raise Exception("Domain size expected to be 2 or 3. Got " + str(self.domain_size)) diff --git a/applications/FSIApplication/python_scripts/partitioned_embedded_fsi_base_solver.py b/applications/FSIApplication/python_scripts/partitioned_embedded_fsi_base_solver.py index c7ea1310af8f..e92d0546fcfc 100644 --- a/applications/FSIApplication/python_scripts/partitioned_embedded_fsi_base_solver.py +++ b/applications/FSIApplication/python_scripts/partitioned_embedded_fsi_base_solver.py @@ -9,47 +9,25 @@ # Importing the Kratos Library import KratosMultiphysics -from KratosMultiphysics.python_solver import PythonSolver # Import applications import KratosMultiphysics.FSIApplication as KratosFSI import KratosMultiphysics.MappingApplication as KratosMapping import KratosMultiphysics.FluidDynamicsApplication as KratosFluid +import KratosMultiphysics.StructuralMechanicsApplication as KratosStructural + +# Import base class +from KratosMultiphysics.FSIApplication.partitioned_fsi_base_solver import PartitionedFSIBaseSolver def CreateSolver(model, project_parameters): return PartitionedEmbeddedFSIBaseSolver(model, project_parameters) -class PartitionedEmbeddedFSIBaseSolver(PythonSolver): +class PartitionedEmbeddedFSIBaseSolver(PartitionedFSIBaseSolver): def __init__(self, model, project_parameters): - # TODO: Remove this as soon as the MPCs are implemented in MPI - # This has to be done prior to the defaults check to avoid the structural solver to throw an error in MPI - if not project_parameters["structure_solver_settings"].Has("multi_point_constraints_used"): - project_parameters["structure_solver_settings"].AddEmptyValue("multi_point_constraints_used") - project_parameters["structure_solver_settings"]["multi_point_constraints_used"].SetBool(False) - - # Call the base Python solver constructor + # Call the base solver constructor super().__init__(model, project_parameters) - # Auxiliar variables - self.parallel_type = self.settings["parallel_type"].GetString() - coupling_settings = self.settings["coupling_settings"] - self.max_nl_it = coupling_settings["nl_max_it"].GetInt() - self.nl_tol = coupling_settings["nl_tol"].GetDouble() - self.structure_interface_submodelpart_name = coupling_settings["structure_interfaces_list"][0].GetString() - - # Construct the structure solver - self.structure_solver = python_solvers_wrapper_structural.CreateSolverByParameters(self.model, self.settings["structure_solver_settings"], self.parallel_type) - KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Structure solver construction finished') - - # Construct the fluid solver - self.fluid_solver = python_solvers_wrapper_fluid.CreateSolverByParameters(self.model, self.settings["fluid_solver_settings"], self.parallel_type) - self.level_set_type = self.settings["fluid_solver_settings"]["formulation"]["level_set_type"].GetString() - - # First call to create the embedded intersections model part - self.__GetEmbedddedSkinUtilityModelPart() - - KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Fluid solver construction finished') KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Partitioned embedded FSI base solver construction finished') @classmethod @@ -82,35 +60,28 @@ def GetDefaultParameters(cls): default_settings.AddMissingParameters(super().GetDefaultParameters()) return default_settings - def ValidateSettings(self): - default_settings = self.GetDefaultParameters() - - ## Base class settings validation - super().ValidateSettings() - - ## Validate coupling settings - self.settings["coupling_settings"].ValidateAndAssignDefaults(default_settings["coupling_settings"]) - - def GetMinimumBufferSize(self): - buffer_fluid = self.fluid_solver.GetMinimumBufferSize() - buffer_structure = self.structure_solver.GetMinimumBufferSize() - return max(buffer_structure,buffer_fluid) - + #TODO: Use the base solver one once we use the fluid ALE solver def AddVariables(self): # Fluid and structure solvers variables addition self.fluid_solver.AddVariables() self.structure_solver.AddVariables() + #TODO: Use the base solver one once we use the fluid ALE solver def ImportModelPart(self): # Fluid and structure solvers ImportModelPart() call self.fluid_solver.ImportModelPart() self.structure_solver.ImportModelPart() + #TODO: Use the base solver one once we use the fluid ALE solver def PrepareModelPart(self): # Fluid and structure solvers PrepareModelPart() call self.fluid_solver.PrepareModelPart() self.structure_solver.PrepareModelPart() + # Perform all the operations required to set up the coupling interfaces + self._InitializeCouplingInterfaces() + + #TODO: Use the base solver one once we use the fluid ALE solver def AddDofs(self): # Add DOFs structure self.structure_solver.AddDofs() @@ -118,17 +89,9 @@ def AddDofs(self): self.fluid_solver.AddDofs() def Initialize(self): - # Get the domain size - self.domain_size = self.__GetDomainSize() - # Coupling utility initialization - # The __GetConvergenceAccelerator is supposed to construct the convergence accelerator in here - self.__GetConvergenceAccelerator().Initialize() - - # FSI interface coupling interfaces initialization - # The __GetFSICouplingInterfaceStructure is supposed to construct the FSI coupling structure interface in here - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart() - self.__GetFSICouplingInterfaceStructure().GetInterfaceModelPart() + # The _GetConvergenceAccelerator is supposed to construct the convergence accelerator in here + self._GetConvergenceAccelerator().Initialize() # Python structure solver initialization self.structure_solver.Initialize() @@ -139,13 +102,7 @@ def Initialize(self): # Compute the fluid domain NODAL_AREA values # Required by the parallel distance calculator if the distance has to be extended if (self.level_set_type == "continuous"): - KratosMultiphysics.CalculateNodalAreaProcess(self.GetFluidComputingModelPart(), self.domain_size).Execute() - - # Initialize the Dirichlet-Neumann interface - self.__InitializeFSIInterfaces() - - # Initialize the iteration value vector - self.__InitializeIterationValueVector() + KratosMultiphysics.CalculateNodalAreaProcess(self.GetFluidComputingModelPart(), self._GetDomainSize()).Execute() # Initialize the distance field update_distance_process = True @@ -156,28 +113,18 @@ def Initialize(self): # Initialize the embedded skin utility self.__GetEmbeddedSkinUtility() - KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', "Finished initialization.") - - def AdvanceInTime(self, current_time): - fluid_new_time = self.fluid_solver.AdvanceInTime(current_time) - structure_new_time = self.structure_solver.AdvanceInTime(current_time) - - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart().GetRootModelPart().CloneTimeStep(fluid_new_time) - self.__GetFSICouplingInterfaceStructure().GetInterfaceModelPart().GetRootModelPart().CloneTimeStep(structure_new_time) + with open("FSI_iterations.txt",'w') as f: + f.write("{}\t{}\t{}\n".format("Step","It.", "err_u")) + f.close() - if abs(fluid_new_time - structure_new_time) > 1e-12: - err_msg = 'Fluid new time is: ' + str(fluid_new_time) + '\n' - err_msg += 'Structure new time is: ' + str(structure_new_time) + '\n' - err_msg += 'No substepping has been implemented yet. Fluid and structure time step must coincide.' - raise Exception(err_msg) - - return fluid_new_time + KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', "Finished initialization.") + #TODO: Use the base one once the body fitted uses the fluid ALE solver def InitializeSolutionStep(self): # Initialize solution step of fluid, structure and coupling solvers self.fluid_solver.InitializeSolutionStep() self.structure_solver.InitializeSolutionStep() - self.__GetConvergenceAccelerator().InitializeSolutionStep() + self._GetConvergenceAccelerator().InitializeSolutionStep() def Predict(self): # Structure solver prediction. It is important to firstly perform the structure @@ -190,138 +137,61 @@ def Predict(self): # Update the level set position with the structure prediction self.__UpdateLevelSet() - # Correct the updated level set - self.fluid_solver.GetDistanceModificationProcess().ExecuteInitializeSolutionStep() - # Fluid solver prediction self.fluid_solver.Predict() - # Restore the fluid node fixity to its original status - self.fluid_solver.GetDistanceModificationProcess().ExecuteFinalizeSolutionStep() - - def GetComputingModelPart(self): - err_msg = 'Calling GetComputingModelPart() method in a partitioned solver.\n' - err_msg += 'Specify the domain of interest by calling:\n' - err_msg += '\t- GetFluidComputingModelPart()\n' - err_msg += '\t- GetStructureComputingModelPart()\n' - raise Exception(err_msg) - - def GetFluidComputingModelPart(self): - return self.fluid_solver.GetComputingModelPart() - - def GetStructureComputingModelPart(self): - return self.structure_solver.GetComputingModelPart() - - def GetStructureSkinModelPart(self): - return self.model.GetModelPart(self.__GetStructureInterfaceModelPartName()) - - def GetStructureSkinElementBasedModelPart(self): - # Create an auxiliar model part to save the element based skin - element_based_skin_model_part_name = self.__GetStructureInterfaceModelPartName() + "ElementBased" - if self.model.HasModelPart(element_based_skin_model_part_name): - self.model.DeleteModelPart(element_based_skin_model_part_name) - self.element_based_skin_model_part = self.model.CreateModelPart(element_based_skin_model_part_name) - - # Copy the skin model part conditions to an auxiliar model part elements. - # This is required for the computation of the distance function, which - # takes the elements of the second modelpart as skin. If this operation - # is not performed, no elements are found, yielding a wrong level set. - self.__GetPartitionedFSIUtilities().CopySkinToElements( - self.GetStructureSkinModelPart(), - self.element_based_skin_model_part) - - return self.element_based_skin_model_part - - def GetStructureIntersectionsModelPart(self): - if not hasattr(self, '_embedded_intersections_model_part'): - embedded_intersections_root_part = self.model.CreateModelPart("EmbeddedIntersectionsModelPart") - self._embedded_intersections_model_part = embedded_intersections_root_part.CreateSubModelPart("SkinEmbeddedIntersectionsModelPart") - self._embedded_intersections_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NORMAL) - self._embedded_intersections_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PRESSURE) - self._embedded_intersections_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VELOCITY) - self._embedded_intersections_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.MESH_VELOCITY) - self._embedded_intersections_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VECTOR_PROJECTED) - return self._embedded_intersections_model_part - - def SolveSolutionStep(self): - ## Non-linear coupling iteration ## - nl_it = 0 - while (nl_it < self.max_nl_it and self.fluid_solver._TimeBufferIsInitialized()): - nl_it += 1 - KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', '\tFSI non-linear iteration = ' + str(nl_it)) - - self.fluid_solver.main_model_part.ProcessInfo[KratosMultiphysics.CONVERGENCE_ACCELERATOR_ITERATION] = nl_it - self.structure_solver.main_model_part.ProcessInfo[KratosMultiphysics.CONVERGENCE_ACCELERATOR_ITERATION] = nl_it - - self.__GetConvergenceAccelerator().InitializeNonLinearIteration() - - # Map the RELAXED_DISP from the structure FSI coupling interface to fluid FSI coupling interface - # This RELAXED_DISP is intended to be used to update the skin position before the level set update - # Note that we take advance of the fact that the coupling interfaces coincide in the embedded case - KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( - KratosMultiphysics.RELAXED_DISPLACEMENT, - KratosMultiphysics.DISPLACEMENT, - self.__GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), - 0) - - # Update the fluid FSI coupling interface position - self.__GetFSICouplingInterfaceFluid().UpdatePosition() - - # Update the EMBEDDED_VELOCITY and solve the fluid problem - self.__SolveFluid() - - # Transfer the fluid load to the structure FSI coupling - self.__TransferFluidLoad() - - # Transfer fluid from the structure FSI coupling interface to father model part - if (self.level_set_type == "continuous"): - self.__GetFSICouplingInterfaceStructure().TransferValuesToFatherModelPart(KratosMultiphysics.POSITIVE_FACE_PRESSURE) - elif (self.level_set_type == "discontinuous"): - self.__GetFSICouplingInterfaceStructure().TransferValuesToFatherModelPart(KratosMultiphysics.POSITIVE_FACE_PRESSURE) - self.__GetFSICouplingInterfaceStructure().TransferValuesToFatherModelPart(KratosMultiphysics.NEGATIVE_FACE_PRESSURE) - else: - err_msg = 'Level set type is: \'' + self.level_set_type + '\'. Expected \'continuous\' or \'discontinuous\'.' - raise Exception(err_msg) - - # Solve the structure problem - self.__SolveStructure() - - # Compute the residual and perform the update - dis_residual_norm = self.__GetFSICouplingInterfaceStructure().Update() - - # End the FSI non-linear iteration - self.__GetConvergenceAccelerator().FinalizeNonLinearIteration() - - # Check convergence - is_converged = self.__CheckFSIConvergence(dis_residual_norm) - if (is_converged): - return True - - return False - + #TODO: Use the base solver one once we use the fluid ALE solver for the fluid def FinalizeSolutionStep(self): # Finalize solution step self.fluid_solver.FinalizeSolutionStep() self.structure_solver.FinalizeSolutionStep() - self.__GetConvergenceAccelerator().FinalizeSolutionStep() - - def SetEchoLevel(self, structure_echo_level, fluid_echo_level): - self.fluid_solver.SetEchoLevel(self, fluid_echo_level) - self.structure_solver.SetEchoLevel(self, structure_echo_level) - - def Clear(self): - self.fluid_solver.Clear() - self.structure_solver.Clear() + self._GetConvergenceAccelerator().FinalizeSolutionStep() - def Check(self): - self.fluid_solver.Check() - self.structure_solver.Check() + #TODO: Use the base solver one once we use the fluid ALE solver for the fluid + def Finalize(self): + self.fluid_solver.Finalize() + self.structure_solver.Finalize() + self._GetConvergenceAccelerator().Finalize() ####################################################################### ############## PRIVATE METHODS SECTION ############## ####################################################################### + def _AuxiliaryInitOperations(self): + # Auxiliar variables + self.parallel_type = self.settings["parallel_type"].GetString() + coupling_settings = self.settings["coupling_settings"] + self.max_nl_it = coupling_settings["nl_max_it"].GetInt() + self.nl_tol = coupling_settings["nl_tol"].GetDouble() + self.structure_interface_submodelpart_name = coupling_settings["structure_interfaces_list"][0].GetString() + + # Construct the structure solver + self.structure_solver = python_solvers_wrapper_structural.CreateSolverByParameters(self.model, self.settings["structure_solver_settings"], self.parallel_type) + KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Structure solver construction finished') + + # Construct the fluid solver + self.fluid_solver = python_solvers_wrapper_fluid.CreateSolverByParameters(self.model, self.settings["fluid_solver_settings"], self.parallel_type) + KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Fluid solver construction finished') + self.level_set_type = self.settings["fluid_solver_settings"]["formulation"]["level_set_type"].GetString() + + # First call to create the embedded intersections model part + self.__GetEmbedddedSkinUtilityModelPart() + + def _AdvanceInTimeCouplingInterfaces(self, new_time): + # Even though these are auxiliary model parts, this is mandatory to be done to properly set up the database + # Note that if this operations are removed, some auxiliary utils (e.g. FM-ALE algorithm in embedded) will perform wrong + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart().GetRootModelPart().CloneTimeStep(new_time) + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart().GetRootModelPart().CloneTimeStep(new_time) + + def _InitializeCouplingInterfaces(self): + # FSI interface coupling interfaces initialization + # The getter methods are to construct the FSI coupling structure interface in here + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart() + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart() + + # Set the INTERFACE flag to the structure skin + KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, self._GetStructureInterfaceSubmodelPart().Nodes) + def __GetDistanceToSkinProcess(self, update_distance_process = False): if update_distance_process: self._distance_to_skin_process = self.__CreateDistanceToSkinProcess() @@ -331,29 +201,29 @@ def __CreateDistanceToSkinProcess(self): # Set the distance computation process if (self.level_set_type == "continuous"): raycasting_relative_tolerance = 1.0e-10 - if self.domain_size == 2: + if self._GetDomainSize() == 2: return KratosMultiphysics.CalculateDistanceToSkinProcess2D( self.GetFluidComputingModelPart(), - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), raycasting_relative_tolerance) - elif self.domain_size == 3: + elif self._GetDomainSize() == 3: return KratosMultiphysics.CalculateDistanceToSkinProcess3D( self.GetFluidComputingModelPart(), - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), raycasting_relative_tolerance) else: - raise Exception("Domain size expected to be 2 or 3. Got " + str(self.domain_size)) + raise Exception("Domain size expected to be 2 or 3. Got " + str(self._GetDomainSize())) elif (self.level_set_type == "discontinuous"): - if self.domain_size == 2: + if self._GetDomainSize() == 2: return KratosMultiphysics.CalculateDiscontinuousDistanceToSkinProcess2D( self.GetFluidComputingModelPart(), - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart()) - elif self.domain_size == 3: + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart()) + elif self._GetDomainSize() == 3: return KratosMultiphysics.CalculateDiscontinuousDistanceToSkinProcess3D( self.GetFluidComputingModelPart(), - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart()) + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart()) else: - raise Exception("Domain size expected to be 2 or 3. Got " + str(self.domain_size)) + raise Exception("Domain size expected to be 2 or 3. Got " + str(self._GetDomainSize())) else: err_msg = 'Level set type is: \'' + self.level_set_type + '\'. Expected \'continuous\' or \'discontinuous\'.' raise Exception(err_msg) @@ -364,12 +234,12 @@ def __GetParallelDistanceCalculator(self): return self._parallel_distance_calculator def __CreateParallelDistanceCalculator(self): - if self.domain_size == 2: + if self._GetDomainSize() == 2: return KratosMultiphysics.ParallelDistanceCalculator2D() - elif self.domain_size == 3: + elif self._GetDomainSize() == 3: return KratosMultiphysics.ParallelDistanceCalculator3D() else: - raise Exception("Domain size expected to be 2 or 3. Got " + str(self.domain_size)) + raise Exception("Domain size expected to be 2 or 3. Got " + str(self._GetDomainSize())) def __GetEmbeddedSkinUtility(self): if not hasattr(self, '_embedded_skin_utility'): @@ -377,18 +247,18 @@ def __GetEmbeddedSkinUtility(self): return self._embedded_skin_utility def __CreateEmbeddedSkinUtility(self): - if self.domain_size == 2: + if self._GetDomainSize() == 2: return KratosMultiphysics.EmbeddedSkinUtility2D( self.GetFluidComputingModelPart(), self.__GetEmbedddedSkinUtilityModelPart(), self.level_set_type) - elif self.domain_size == 3: + elif self._GetDomainSize() == 3: return KratosMultiphysics.EmbeddedSkinUtility3D( self.GetFluidComputingModelPart(), self.__GetEmbedddedSkinUtilityModelPart(), self.level_set_type) else: - raise Exception("Domain size expected to be 2 or 3. Got " + str(self.domain_size)) + raise Exception("Domain size expected to be 2 or 3. Got " + str(self._GetDomainSize())) def __GetEmbedddedSkinUtilityModelPart(self): if not hasattr(self, '_embedded_skin_utility_model_part'): @@ -409,27 +279,6 @@ def __CreateEmbeddedSkinUtilityModelPart(self): raise Exception(err_msg) return embedded_skin_utility_skin_model_part - def __GetStructureInterfaceModelPartName(self): - str_int_list = self.settings["coupling_settings"]["structure_interfaces_list"] - if (str_int_list.size() != 1): - raise Exception("FSI embedded solver structure skin must be contained in a unique model part") - return str_int_list[0].GetString() - - def __InitializeIterationValueVector(self): - # Note that the embedded FSI problem is defined in terms of the structure interface - # Initialize the iteration value for the residual computation - str_int_res_size = self.__GetPartitionedFSIUtilities().GetInterfaceResidualSize(self.__GetStructureInterfaceSubmodelPart()) - self.iteration_value = KratosMultiphysics.Vector(str_int_res_size) - for i in range(0,str_int_res_size): - self.iteration_value[i] = 0.0 - - def __InitializeFSIInterfaces(self): - # Initialize Neumann structure interface - str_interface_submodelpart = self.model.GetModelPart(self.__GetStructureInterfaceModelPartName()) - - # Set the INTERFACE flag to the structure skin - KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, str_interface_submodelpart.Nodes) - def __UpdateLevelSet(self): # Recompute the distance field with the obtained solution self.__GetDistanceToSkinProcess().Execute() @@ -452,28 +301,31 @@ def __ExtendLevelSet(self): max_layers, max_distance) - def __SolveFluid(self): + def _MapStructureInterfaceDisplacement(self): + # Map the RELAXED_DISP from the structure FSI coupling interface to fluid FSI coupling interface + # Note that we take advance of the fact that the coupling interfaces coincide in the embedded case + # Then update the fluid FSI coupling interface position + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( + KratosMultiphysics.RELAXED_DISPLACEMENT, + KratosMultiphysics.DISPLACEMENT, + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), + 0) + self._GetFSICouplingInterfaceFluid().UpdatePosition(KratosMultiphysics.DISPLACEMENT) + + def _SolveFluid(self): # Update the current iteration level-set position self.__UpdateLevelSet() # Solve fluid problem self.fluid_solver.SolveSolutionStep() # This contains the FM-ALE operations and the level set correction - def __TransferFluidLoad(self): + def _CalculateFluidInterfaceTraction(self): if (self.level_set_type == "continuous"): # Interpolate the pressure to the fluid FSI coupling interface - self.__GetPartitionedFSIUtilities().EmbeddedPressureToPositiveFacePressureInterpolator( + self._GetPartitionedFSIUtilities().EmbeddedPressureToPositiveFacePressureInterpolator( self.GetFluidComputingModelPart(), - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart()) - - # Map PRESSURE from fluid FSI coupling interface to structure FSI coupling interface - # Note that in here we take advantage of the fact that the coupling interfaces coincide in the embedded case - KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( - KratosMultiphysics.PRESSURE, - KratosMultiphysics.POSITIVE_FACE_PRESSURE, - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), - self.__GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), - 0) + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart()) elif (self.level_set_type == "discontinuous"): # Generate the intersections skin to map from @@ -485,13 +337,40 @@ def __TransferFluidLoad(self): self.__GetEmbeddedSkinUtility().InterpolateDiscontinuousMeshVariableToSkin( KratosMultiphysics.PRESSURE, KratosMultiphysics.NEGATIVE_FACE_PRESSURE, "negative") + else: + err_msg = 'Level set type is: \'' + self.level_set_type + '\'. Expected \'continuous\' or \'discontinuous\'.' + raise Exception(err_msg) + + def _MapFluidInterfaceTraction(self): + if (self.level_set_type == "continuous"): + # Map PRESSURE from fluid FSI coupling interface to structure FSI coupling interface + # Note that in here we take advantage of the fact that the coupling interfaces coincide in the embedded case + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( + KratosMultiphysics.POSITIVE_FACE_PRESSURE, + KratosMultiphysics.POSITIVE_FACE_PRESSURE, + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + 0) + + # Convert the pressure scalar load to a traction vector one + swap_traction_sign = True + self._GetPartitionedFSIUtilities().CalculateTractionFromPressureValues( + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + KratosMultiphysics.POSITIVE_FACE_PRESSURE, + self._GetTractionVariable(), + swap_traction_sign) + + elif (self.level_set_type == "discontinuous"): + # Map the POSITIVE_FACE_PRESSURE and NEGATIVE_FACE_PRESSURE from the auxiliary embedded skin model part, + # which is created from the elemental level set intersections, to the fluid FSI coupling interface + # Note that the mapper instance is created each time as the embedded skin mesh potentially changes at each iteration mapper_params = KratosMultiphysics.Parameters("""{ "mapper_type": "nearest_element", "echo_level" : 0 }""") mapper = KratosMapping.MapperFactory.CreateMapper( self.__GetEmbedddedSkinUtilityModelPart(), - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), mapper_params) mapper.Map(KratosMultiphysics.POSITIVE_FACE_PRESSURE, KratosMultiphysics.POSITIVE_FACE_PRESSURE) mapper.Map(KratosMultiphysics.NEGATIVE_FACE_PRESSURE, KratosMultiphysics.NEGATIVE_FACE_PRESSURE) @@ -500,81 +379,71 @@ def __TransferFluidLoad(self): # Note that in here we take advantage of the fact that the coupling interfaces coincide in the embedded case KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( KratosMultiphysics.POSITIVE_FACE_PRESSURE, - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), - self.__GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), 0) KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( KratosMultiphysics.NEGATIVE_FACE_PRESSURE, - self.__GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), - self.__GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluid().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), 0) + + # Convert the pressure scalar load to a traction vector one + swap_traction_sign = True + self._GetPartitionedFSIUtilities().CalculateTractionFromPressureValues( + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + KratosMultiphysics.POSITIVE_FACE_PRESSURE, + KratosMultiphysics.NEGATIVE_FACE_PRESSURE, + self._GetTractionVariable(), + swap_traction_sign) + else: err_msg = 'Level set type is: \'' + self.level_set_type + '\'. Expected \'continuous\' or \'discontinuous\'.' raise Exception(err_msg) - def __SolveStructure(self): + #TODO: Use the base solver one once the body-fitted does not require to do the traction to point load conversion + def _SolveStructure(self): # Solve the structure problem self.structure_solver.SolveSolutionStep() - def __CheckFSIConvergence(self, residual_norm): - interface_dofs = self.__GetPartitionedFSIUtilities().GetInterfaceResidualSize(self.__GetStructureInterfaceSubmodelPart()) - normalised_residual = residual_norm/sqrt(interface_dofs) - KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', '\t|res|/sqrt(nDOFS) = ' + str(normalised_residual)) - return normalised_residual < self.nl_tol - - # This method returns the convergence accelerator. - # If it is not created yet, it calls the __CreateConvergenceAccelerator first - def __GetConvergenceAccelerator(self): - if not hasattr(self, '_convergence_accelerator'): - self._convergence_accelerator = self.__CreateConvergenceAccelerator() - return self._convergence_accelerator - - # This method constructs the convergence accelerator coupling utility - def __CreateConvergenceAccelerator(self): - convergence_accelerator = convergence_accelerator_factory.CreateConvergenceAccelerator(self.settings["coupling_settings"]["coupling_strategy_settings"]) - KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Coupling strategy construction finished') - return convergence_accelerator - - def __GetFSICouplingInterfaceStructure(self): - if not hasattr(self, '_fsi_coupling_interface_structure'): - self._fsi_coupling_interface_structure = self.__CreateFSICouplingInterfaceStructure() - return self._fsi_coupling_interface_structure - - def __CreateFSICouplingInterfaceStructure(self): + def _CreateFSICouplingInterfaceStructure(self): # Set auxiliary settings if (self.level_set_type == "continuous"): aux_settings = KratosMultiphysics.Parameters( """{ "model_part_name": "FSICouplingInterfaceStructure", "parent_model_part_name": "", - "input_variable_list": ["POSITIVE_FACE_PRESSURE"], - "output_variable_list": ["DISPLACEMENT"] + "input_variable_list": [], + "output_variable_list": ["DISPLACEMENT"], + "auxiliary_variable_list": ["POSITIVE_FACE_PRESSURE","NORMAL"] }""") elif (self.level_set_type == "discontinuous"): aux_settings = KratosMultiphysics.Parameters( """{ "model_part_name": "FSICouplingInterfaceStructure", "parent_model_part_name": "", - "input_variable_list": ["POSITIVE_FACE_PRESSURE","NEGATIVE_FACE_PRESSURE"], - "output_variable_list": ["DISPLACEMENT"] + "input_variable_list": [], + "output_variable_list": ["DISPLACEMENT"], + "auxiliary_variable_list": ["POSITIVE_FACE_PRESSURE","NEGATIVE_FACE_PRESSURE","NORMAL"] }""") else: err_msg = 'Level set type is: \'' + self.level_set_type + '\'. Expected \'continuous\' or \'discontinuous\'.' raise Exception(err_msg) aux_settings["parent_model_part_name"].SetString(self.structure_interface_submodelpart_name) + aux_settings["input_variable_list"].Append(self._GetTractionVariable().Name()) # Construct the FSI coupling interface fsi_coupling_interface_structure = fsi_coupling_interface.FSICouplingInterface( self.model, aux_settings, - self.__GetConvergenceAccelerator()) + self._GetConvergenceAccelerator()) KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Structure FSI coupling interface created') return fsi_coupling_interface_structure - def __GetFSICouplingInterfaceFluid(self): + def _GetFSICouplingInterfaceFluid(self): if not hasattr(self, '_fsi_coupling_interface_fluid'): self._fsi_coupling_interface_fluid = self.__CreateFSICouplingInterfaceFluid() return self._fsi_coupling_interface_fluid @@ -589,7 +458,7 @@ def __CreateFSICouplingInterfaceFluid(self): "model_part_name": "FSICouplingInterfaceFluid", "parent_model_part_name": "", "input_variable_list": ["DISPLACEMENT"], - "output_variable_list": ["PRESSURE"] + "output_variable_list": ["POSITIVE_FACE_PRESSURE"] }""") elif (self.level_set_type == "discontinuous"): aux_settings = KratosMultiphysics.Parameters( @@ -614,28 +483,22 @@ def __CreateFSICouplingInterfaceFluid(self): return fsi_coupling_interface_fluid - def __GetStructureInterfaceSubmodelPart(self): - # Returns the structure interface submodelpart that will be used in the residual minimization - return self.model.GetModelPart(self.structure_interface_submodelpart_name) - - def __GetDomainSize(self): - fluid_domain_size = self.fluid_solver.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] - structure_domain_size = self.structure_solver.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] - - if fluid_domain_size !=structure_domain_size: - raise("ERROR: Solid domain size and fluid domain size are not equal!") - - return fluid_domain_size + @classmethod + def _GetFSICouplingInterfaceFluidPositive(self): + err_msg = 'Embedded partitioned FSI solver does not implement the \'_GetFSICouplingInterfaceFluidPositive\' method.\n' + err_msg += 'Use \'_GetFSICouplingInterfaceFluid\' method as the fluid coupling interface is unique.' + raise Exception(err_msg) - def __GetPartitionedFSIUtilities(self): - if not hasattr(self, '_partitioned_fsi_utilities'): - self._partitioned_fsi_utilities = self.__CreatePartitionedFSIUtilities() - return self._partitioned_fsi_utilities + @classmethod + def _GetFSICouplingInterfaceFluidNegative(self): + err_msg = 'Embedded partitioned FSI solver does not implement the \'_GetFSICouplingInterfaceFluidNegative\' method.\n' + err_msg += 'Use \'_GetFSICouplingInterfaceFluid\' method as the fluid coupling interface is unique.' + raise Exception(err_msg) - def __CreatePartitionedFSIUtilities(self): - if self.domain_size == 2: - return KratosFSI.PartitionedFSIUtilitiesArray2D() - elif self.domain_size == 3: - return KratosFSI.PartitionedFSIUtilitiesArray3D() + def _GetTractionVariable(self): + if self._GetDomainSize() == 2: + return KratosStructural.LINE_LOAD + elif self._GetDomainSize() == 3: + return KratosStructural.SURFACE_LOAD else: - raise Exception("Domain size expected to be 2 or 3. Got " + str(self.domain_size)) + raise Exception("Domain size expected to be 2 or 3. Got " + str(self._GetDomainSize())) diff --git a/applications/FSIApplication/python_scripts/partitioned_fsi_base_solver.py b/applications/FSIApplication/python_scripts/partitioned_fsi_base_solver.py index 735dbb55e06e..dd5fe9a52011 100755 --- a/applications/FSIApplication/python_scripts/partitioned_fsi_base_solver.py +++ b/applications/FSIApplication/python_scripts/partitioned_fsi_base_solver.py @@ -2,10 +2,10 @@ from math import sqrt # Import the square root from python library # Import utilities -from KratosMultiphysics.FSIApplication import NonConformant_OneSideMap # Import non-conformant mapper from KratosMultiphysics.FluidDynamicsApplication import python_solvers_wrapper_fluid # Import the fluid Python solvers wrapper from KratosMultiphysics.StructuralMechanicsApplication import python_solvers_wrapper_structural # Import the structure Python solvers wrapper from KratosMultiphysics.MeshMovingApplication import python_solvers_wrapper_mesh_motion # Import the mesh motion Python solvers wrapper +from KratosMultiphysics.FSIApplication import fsi_coupling_interface # Import the FSI coupling interface utility from KratosMultiphysics.FSIApplication import convergence_accelerator_factory # Import the FSI convergence accelerator factory # Importing the Kratos Library @@ -14,6 +14,7 @@ # Import applications import KratosMultiphysics.FSIApplication as KratosFSI +import KratosMultiphysics.MappingApplication as KratosMapping import KratosMultiphysics.StructuralMechanicsApplication as KratosStructural def CreateSolver(model, project_parameters): @@ -31,80 +32,11 @@ def __init__(self, model, project_parameters): # Note that default settings in GetDefaultParameters() are validated in here super().__init__(model, project_parameters) - # Auxiliar variables - self.parallel_type = self.settings["parallel_type"].GetString() - coupling_settings = self.settings["coupling_settings"] - self.max_nl_it = coupling_settings["nl_max_it"].GetInt() - self.nl_tol = coupling_settings["nl_tol"].GetDouble() - self.solve_mesh_at_each_iteration = coupling_settings["solve_mesh_at_each_iteration"].GetBool() - self.fluid_interface_submodelpart_name = coupling_settings["fluid_interfaces_list"][0].GetString() - self.structure_interface_submodelpart_name = coupling_settings["structure_interfaces_list"][0].GetString() - - ## Construct the structure solver - self.structure_solver = python_solvers_wrapper_structural.CreateSolverByParameters(self.model, self.settings["structure_solver_settings"], self.parallel_type) - KratosMultiphysics.Logger.PrintInfo("::[PartitionedFSIBaseSolver]::", "Structure solver construction finished.") - - ## Construct the fluid solver - self.fluid_solver = python_solvers_wrapper_fluid.CreateSolverByParameters(self.model, self.settings["fluid_solver_settings"], self.parallel_type) - KratosMultiphysics.Logger.PrintInfo("::[PartitionedFSIBaseSolver]::", "Fluid solver construction finished.") - - ## Check the ALE settings before the mesh solver construction - mesh_solver_settings = self.settings["mesh_solver_settings"] - fluid_solver_settings = self.settings["fluid_solver_settings"] + # This method encapsulates all the operations required to be done in the constructor + # It is intended to be overwritten in the derived classes + self._AuxiliaryInitOperations() - # Check that the ALE and the fluid are the same model part - fluid_model_part_name = fluid_solver_settings["model_part_name"].GetString() - if mesh_solver_settings.Has("model_part_name"): - if not fluid_model_part_name == mesh_solver_settings["model_part_name"].GetString(): - err_msg = 'Fluid and mesh solver have to use the same MainModelPart ("model_part_name")!\n' - raise Exception(err_msg) - else: - mesh_solver_settings.AddValue("model_part_name", fluid_solver_settings["model_part_name"]) - - # Ensure that the fluid domain is not imported twice - if mesh_solver_settings.Has("model_import_settings"): - if mesh_solver_settings["model_import_settings"].Has("input_type"): - if not mesh_solver_settings["model_import_settings"]["input_type"].GetString() == "use_input_model_part": - mesh_solver_settings["model_import_settings"]["input_type"].SetString("use_input_model_part") - else: - mesh_solver_settings["model_import_settings"].AddEmptyValue("input_type").SetString("use_input_model_part") - else: - mesh_solver_settings.AddEmptyValue("model_import_settings").AddEmptyValue("input_type").SetString("use_input_model_part") - - # Check that the ALE and the fluid have the sime time scheme - if fluid_solver_settings.Has("time_scheme"): - fluid_time_scheme = fluid_solver_settings["time_scheme"].GetString() - if mesh_solver_settings.Has("mesh_velocity_calculation"): - if mesh_solver_settings["mesh_velocity_calculation"].Has("time_scheme"): - if not fluid_time_scheme == mesh_solver_settings["mesh_velocity_calculation"]["time_scheme"].GetString(): - err_msg = 'Fluid and mesh solver require to use the same time scheme ("time_scheme") for consistency!\n' - raise Exception(err_msg) - else: - mesh_solver_settings["mesh_velocity_calculation"].AddValue("time_scheme", fluid_solver_settings["time_scheme"]) - else: - mesh_solver_settings.AddEmptyValue("mesh_velocity_calculation") - mesh_solver_settings["mesh_velocity_calculation"].AddValue("time_scheme", fluid_solver_settings["time_scheme"]) - - # Check domain size - fluid_domain_size = fluid_solver_settings["domain_size"].GetInt() - if mesh_solver_settings.Has("domain_size"): - if not fluid_domain_size == mesh_solver_settings["domain_size"].GetInt(): - raise Exception('Fluid and mesh solver have different "domain_size"!') - else: - mesh_solver_settings.AddValue("domain_size", fluid_solver_settings["domain_size"]) - - # Ensure that the MESH_VELOCITY is computed - if mesh_solver_settings.Has("calculate_mesh_velocity"): - if not mesh_solver_settings["calculate_mesh_velocity"].GetBool(): - mesh_solver_settings.SetValue("calculate_mesh_velocity", True) - KratosMultiphysics.Logger.PrintWarning("","Mesh velocity calculation was deactivated. Switching \"calculate_mesh_velocity\" on") - else: - mesh_solver_settings.AddEmptyValue("calculate_mesh_velocity").SetBool(True) - - ## Construct the ALE mesh solver - self.mesh_solver = python_solvers_wrapper_mesh_motion.CreateSolverByParameters(self.model, self.settings["mesh_solver_settings"], self.parallel_type) - KratosMultiphysics.Logger.PrintInfo("::[PartitionedFSIBaseSolver]::", "ALE mesh solver construction finished.") - KratosMultiphysics.Logger.PrintInfo("::[PartitionedFSIBaseSolver]::", "Partitioned FSI base solver construction finished.") + KratosMultiphysics.Logger.PrintInfo("PartitionedFSIBaseSolver", "Partitioned FSI base solver construction finished.") @classmethod def GetDefaultParameters(cls): @@ -115,6 +47,7 @@ def GetDefaultParameters(cls): "echo_level": 0, "parallel_type": "OpenMP", "solver_type": "partitioned", + "coupling_scheme": "dirichlet_neumann", "structure_solver_settings": { }, "fluid_solver_settings":{ @@ -167,19 +100,13 @@ def AddVariables(self): ## Fluid variables addition # Standard CFD variables addition self.fluid_solver.AddVariables() - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.FORCE) - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.MESH_ACCELERATION) # TODO: This should be added in the mesh solvers # Mesh solver variables addition self.mesh_solver.AddVariables() - ## FSIApplication variables addition - NonConformant_OneSideMap.AddVariables(self.fluid_solver.main_model_part,self.structure_solver.main_model_part) - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VECTOR_PROJECTED) - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.FSI_INTERFACE_RESIDUAL) - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.FSI_INTERFACE_MESH_RESIDUAL) - self.structure_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE) - self.structure_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE) - self.structure_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VECTOR_PROJECTED) + ## Fluid traction variables addition + # These are required for the reaction variable redistribution in the fluid model part skin + self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE) + self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE) def ImportModelPart(self): # Fluid and structure solvers ImportModelPart() call @@ -188,13 +115,18 @@ def ImportModelPart(self): self.mesh_solver.ImportModelPart() def PrepareModelPart(self): - # Get the minimum buffer size between the mesh, fluid and structure solvers - self._GetAndSetMinimumBufferSize() # Fluid and structure solvers PrepareModelPart() call self.structure_solver.PrepareModelPart() self.fluid_solver.PrepareModelPart() self.mesh_solver.PrepareModelPart() + # FSI interface coupling interfaces initialization + # The getter methods are to construct the FSI coupling interfaces in here + self._GetFSICouplingInterfaceFluidPositive().GetInterfaceModelPart() + if self.double_faced_structure: + self._GetFSICouplingInterfaceFluidNegative().GetInterfaceModelPart() + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart() + def AddDofs(self): # Add DOFs structure self.structure_solver.AddDofs() @@ -204,11 +136,33 @@ def AddDofs(self): self.mesh_solver.AddDofs() def Initialize(self): - err_msg = 'Calling the base partitioned FSI solver Initialize() method.\n' - err_msg += 'Implement the custom Initialize() method in the derived solver.' - raise Exception(err_msg) + # Create the required mappers + self._GetStructureToFluidPositiveInterfaceMapper() + if self.double_faced_structure: + self._GetStructureToFluidNegativeInterfaceMapper() + + # Coupling utility initialization + # The _GetConvergenceAccelerator is supposed to construct the convergence accelerator in here + self._GetConvergenceAccelerator().Initialize() + + # Python structure solver initialization + self.structure_solver.Initialize() + + # Ensure that the fluid reaction fluxes are computed before initializing the fluid strategy + if self.fluid_solver.settings["compute_reactions"].GetBool() == False: + self.fluid_solver.settings["compute_reactions"].SetBool(True) + + # Python fluid solver initialization + self.fluid_solver.Initialize() + + # Python mesh solver initialization + self.mesh_solver.Initialize() + + # Perform all the operations required to set up the coupling interfaces + self._InitializeCouplingInterfaces() def AdvanceInTime(self, current_time): + # Subdomains time advance fluid_new_time = self.fluid_solver.AdvanceInTime(current_time) structure_new_time = self.structure_solver.AdvanceInTime(current_time) @@ -218,6 +172,10 @@ def AdvanceInTime(self, current_time): err_msg += 'No substepping has been implemented yet. Fluid and structure time must coincide.' raise Exception(err_msg) + # Update the auxiliary coupling interface model parts database in case these are to be output + # Note that there are also situations (e.g. embedded) in which this is mandatory for the proper performance of the solver + self._AdvanceInTimeCouplingInterfaces(fluid_new_time) + return fluid_new_time def InitializeSolutionStep(self): @@ -253,72 +211,75 @@ def SaveRestart(self): pass def SolveSolutionStep(self): - ## Solvers initialization - self.InitializeSolutionStep() - - ## Solvers predict - self.Predict() + ## Safe ward to avoid coupling if fluid problem is not initialized + if not self.fluid_solver._TimeBufferIsInitialized(): + return True - ## Compute mesh prediction ## - if (self.double_faced_structure): - self._ComputeMeshPredictionDoubleFaced() - else: - self._ComputeMeshPredictionSingleFaced() - KratosMultiphysics.Logger.PrintInfo("","\tMesh prediction computed.") + ## Initialize residual + dis_residual_norm = self._ComputeInitialResidual() - ## Non-Linear interface coupling iteration ## + ## FSI nonlinear iteration loop nl_it = 0 is_converged = False - while not is_converged: - nl_it += 1 - KratosMultiphysics.Logger.PrintInfo("","\tFSI non-linear iteration = ", nl_it) - - self.fluid_solver.main_model_part.ProcessInfo[KratosMultiphysics.CONVERGENCE_ACCELERATOR_ITERATION] = nl_it - self.structure_solver.main_model_part.ProcessInfo[KratosMultiphysics.CONVERGENCE_ACCELERATOR_ITERATION] = nl_it + while (nl_it < self.max_nl_it): + # Check convergence + if self._CheckFSIConvergence(nl_it, dis_residual_norm): + KratosMultiphysics.Logger.PrintInfo('PartitionedFSIBaseSolver', 'FSI non-linear iteration convergence achieved in {0} iterations.'.format(nl_it)) + is_converged = True + break + # Perform the displacement convergence accelerator update self._GetConvergenceAccelerator().InitializeNonLinearIteration() + if not self._GetConvergenceAccelerator().IsBlockNewton(): + self._GetFSICouplingInterfaceStructure().Update() + else: + self._GetFSICouplingInterfaceStructure().UpdateDisplacement() - # Solve the mesh problem as well as the fluid problem - self._SolveMeshAndFluid() + # Update the structure interface position + self._GetFSICouplingInterfaceStructure().UpdatePosition(KratosMultiphysics.RELAXED_DISPLACEMENT) - # Solve the structure problem and computes the displacement residual - if (self.double_faced_structure): - self._SolveStructureDoubleFaced() - dis_residual = self._ComputeDisplacementResidualDoubleFaced() - else: - self._SolveStructureSingleFaced() - dis_residual = self._ComputeDisplacementResidualSingleFaced() + # Map the relaxed displacement from the structure coupling interface to the fluid one + self._MapStructureInterfaceDisplacement() - # Residual computation - nl_res_norm = self.fluid_solver.main_model_part.ProcessInfo[KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM] - interface_dofs = self.partitioned_fsi_utilities.GetInterfaceResidualSize(self._GetFluidInterfaceSubmodelPart()) + # Solve the mesh and fluid problem + self._SolveFluid() - # Check convergence - if nl_res_norm/sqrt(interface_dofs) < self.nl_tol: - is_converged = True - self._GetConvergenceAccelerator().FinalizeNonLinearIteration() - KratosMultiphysics.Logger.PrintInfo("","\tNon-linear iteration convergence achieved") - KratosMultiphysics.Logger.PrintInfo("","\tTotal non-linear iterations: ", nl_it, " |res|/sqrt(nDOFS) = ", nl_res_norm/sqrt(interface_dofs)) - break + # Calculate the fluid interface traction from the interface reaction + #TODO: THINK ABOUT COMPUTING THE SUM OF NEGATIVE AND POSITIVE DISTRIBUTED LOAD AND TRANSFER THIS TO THE STRUCTURE (INSTEAD OF PASSING POSITIVE AND NEGATIVE) + self._CalculateFluidInterfaceTraction() + + # Transfer the fluid traction to the structure interface + self._MapFluidInterfaceTraction() + + # Compute the current iteration traction + if not self._GetConvergenceAccelerator().IsBlockNewton(): + # Directly send the map load from the structure FSI coupling interface to the parent one + self._GetFSICouplingInterfaceStructure().TransferValuesToFatherModelPart(self._GetTractionVariable()) else: - # If convergence is not achieved, perform the correction of the prediction - KratosMultiphysics.Logger.PrintInfo("","\tResidual computation finished. |res|/sqrt(nDOFS) = ", nl_res_norm/sqrt(interface_dofs)) - self._GetConvergenceAccelerator().UpdateSolution(dis_residual, self.iteration_value) - self._GetConvergenceAccelerator().FinalizeNonLinearIteration() - - if (nl_it == self.max_nl_it): - KratosMultiphysics.Logger.PrintWarning("","\tFSI NON-LINEAR ITERATION CONVERGENCE NOT ACHIEVED") - break - - ## Compute the mesh residual as final testing (it is expected to be 0) - mesh_res_norm = self.partitioned_fsi_utilities.ComputeInterfaceResidualNorm( - self._GetFluidInterfaceSubmodelPart(), - KratosMultiphysics.VELOCITY, - KratosMultiphysics.MESH_VELOCITY, - KratosMultiphysics.FSI_INTERFACE_MESH_RESIDUAL, - "nodal") - KratosMultiphysics.Logger.PrintInfo("","\tNL residual norm: ", nl_res_norm) - KratosMultiphysics.Logger.PrintInfo("","\tMesh residual norm: ", mesh_res_norm) + # Perform the traction convergence accelerator update + self._GetFSICouplingInterfaceStructure().UpdateTraction() + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( + KratosMultiphysics.RELAXED_TRACTION, + self._GetTractionVariable(), + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceStructure().GetFatherModelPart(), + 0) + #TODO: Remove as soon as the CopyModelPartNodalVar synchronizes internally + self._GetFSICouplingInterfaceStructure().GetFatherModelPart().GetCommunicator().SynchronizeVariable(self._GetTractionVariable()) + + self._GetConvergenceAccelerator().FinalizeNonLinearIteration() + + # Solve the structure problem + self._SolveStructure() + + # Compute the residual vector + dis_residual_norm = self._GetFSICouplingInterfaceStructure().ComputeResidualVector() + + # Check and update iterator counter + if nl_it == self.max_nl_it: + KratosMultiphysics.Logger.PrintInfo('PartitionedFSIBaseSolver', 'FSI non-linear converged not achieved in {0} iterations'.format(self.max_nl_it)) + else: + nl_it += 1 return is_converged @@ -328,14 +289,16 @@ def FinalizeSolutionStep(self): self.mesh_solver.FinalizeSolutionStep() self._GetConvergenceAccelerator().FinalizeSolutionStep() + def Finalize(self): + self.structure_solver.Finalize() + self.fluid_solver.Finalize() + self.mesh_solver.Finalize() + self._GetConvergenceAccelerator().Finalize() + def SetEchoLevel(self, structure_echo_level, fluid_echo_level): self.structure_solver.SetEchoLevel(self, structure_echo_level) self.fluid_solver.SetEchoLevel(self, fluid_echo_level) - def SetTimeStep(self, step): - self.fluid_solver.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.STEP, step) - self.structure_solver.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.STEP, step) - def Clear(self): self.fluid_solver.Clear() self.structure_solver.Clear() @@ -348,18 +311,108 @@ def Check(self): ############## PRIVATE METHODS SECTION ############## ####################################################################### - # This method returns the convergence accelerator. - # If it is not created yet, it calls the _CreateConvergenceAccelerator first - def _GetConvergenceAccelerator(self): - if not hasattr(self, '_convergence_accelerator'): - self._convergence_accelerator = self._CreateConvergenceAccelerator() - return self._convergence_accelerator + def _AuxiliaryInitOperations(self): + # Auxiliar variables + self.parallel_type = self.settings["parallel_type"].GetString() + coupling_settings = self.settings["coupling_settings"] + self.max_nl_it = coupling_settings["nl_max_it"].GetInt() + self.nl_tol = coupling_settings["nl_tol"].GetDouble() + self.solve_mesh_at_each_iteration = coupling_settings["solve_mesh_at_each_iteration"].GetBool() - # This method constructs the convergence accelerator coupling utility - def _CreateConvergenceAccelerator(self): - convergence_accelerator = convergence_accelerator_factory.CreateConvergenceAccelerator(self.settings["coupling_settings"]["coupling_strategy_settings"]) - KratosMultiphysics.Logger.PrintInfo("::[PartitionedFSIBaseSolver]::", "Coupling strategy construction finished.") - return convergence_accelerator + ## Save the FSI interfaces information in a dictionary + mappers_settings = self.settings["coupling_settings"]["mapper_settings"] + self.interfaces_dict = {} + self.interfaces_dict['structure'] = coupling_settings["structure_interfaces_list"][0].GetString() + if mappers_settings.size() == 1: + self.double_faced_structure = False + self.interfaces_dict['fluid_positive'] = mappers_settings[0]["fluid_interface_submodelpart_name"].GetString() + self.interfaces_dict['fluid_negative'] = None + elif mappers_settings.size() == 2: + self.double_faced_structure = True + for mapper_id in range(2): + if (mappers_settings[mapper_id]["mapper_face"].GetString() == "Positive"): + self.interfaces_dict['fluid_positive'] = mappers_settings[mapper_id]["fluid_interface_submodelpart_name"].GetString() + elif (mappers_settings[mapper_id]["mapper_face"].GetString() == "Negative"): + self.interfaces_dict['fluid_negative'] = mappers_settings[mapper_id]["fluid_interface_submodelpart_name"].GetString() + else: + err_msg = "The mapper face is not \'Positve\' nor \'Negative\'." + raise Exception(err_msg) + else: + err_msg = "Case with more than 2 mappers has not been implemented yet.\n" + err_msg += "Please, in case you are using single faced immersed bodies, set the skin entities in a unique submodelpart.\n" + err_msg += "In case you are considering double faced immersed bodies (shells or membranes), set all the positive faces in a unique submodelpart and all the negative ones in another submodelpart." + raise Exception(err_msg) + + ## Construct the structure solver + self.structure_solver = python_solvers_wrapper_structural.CreateSolverByParameters(self.model, self.settings["structure_solver_settings"], self.parallel_type) + KratosMultiphysics.Logger.PrintInfo("PartitionedFSIBaseSolver", "Structure solver construction finished.") + + ## Construct the fluid solver + self.fluid_solver = python_solvers_wrapper_fluid.CreateSolverByParameters(self.model, self.settings["fluid_solver_settings"], self.parallel_type) + KratosMultiphysics.Logger.PrintInfo("PartitionedFSIBaseSolver", "Fluid solver construction finished.") + + ## Check the ALE settings before the mesh solver construction + mesh_solver_settings = self.settings["mesh_solver_settings"] + fluid_solver_settings = self.settings["fluid_solver_settings"] + + # Check that the ALE and the fluid are the same model part + fluid_model_part_name = fluid_solver_settings["model_part_name"].GetString() + if mesh_solver_settings.Has("model_part_name"): + if not fluid_model_part_name == mesh_solver_settings["model_part_name"].GetString(): + err_msg = 'Fluid and mesh solver have to use the same MainModelPart ("model_part_name")!\n' + raise Exception(err_msg) + else: + mesh_solver_settings.AddValue("model_part_name", fluid_solver_settings["model_part_name"]) + + # Ensure that the fluid domain is not imported twice + if mesh_solver_settings.Has("model_import_settings"): + if mesh_solver_settings["model_import_settings"].Has("input_type"): + if not mesh_solver_settings["model_import_settings"]["input_type"].GetString() == "use_input_model_part": + mesh_solver_settings["model_import_settings"]["input_type"].SetString("use_input_model_part") + else: + mesh_solver_settings["model_import_settings"].AddEmptyValue("input_type").SetString("use_input_model_part") + else: + mesh_solver_settings.AddEmptyValue("model_import_settings").AddEmptyValue("input_type").SetString("use_input_model_part") + + # Check that the ALE and the fluid have the sime time scheme + if fluid_solver_settings.Has("time_scheme"): + fluid_time_scheme = fluid_solver_settings["time_scheme"].GetString() + if mesh_solver_settings.Has("mesh_velocity_calculation"): + if mesh_solver_settings["mesh_velocity_calculation"].Has("time_scheme"): + if not fluid_time_scheme == mesh_solver_settings["mesh_velocity_calculation"]["time_scheme"].GetString(): + err_msg = 'Fluid and mesh solver require to use the same time scheme ("time_scheme") for consistency!\n' + raise Exception(err_msg) + else: + mesh_solver_settings["mesh_velocity_calculation"].AddValue("time_scheme", fluid_solver_settings["time_scheme"]) + else: + mesh_solver_settings.AddEmptyValue("mesh_velocity_calculation") + mesh_solver_settings["mesh_velocity_calculation"].AddValue("time_scheme", fluid_solver_settings["time_scheme"]) + + # Check domain size + fluid_domain_size = fluid_solver_settings["domain_size"].GetInt() + if mesh_solver_settings.Has("domain_size"): + if not fluid_domain_size == mesh_solver_settings["domain_size"].GetInt(): + raise Exception('Fluid and mesh solver have different "domain_size"!') + else: + mesh_solver_settings.AddValue("domain_size", fluid_solver_settings["domain_size"]) + + # Ensure that the MESH_VELOCITY is computed + if mesh_solver_settings.Has("calculate_mesh_velocity"): + if not mesh_solver_settings["calculate_mesh_velocity"].GetBool(): + mesh_solver_settings.SetValue("calculate_mesh_velocity", True) + KratosMultiphysics.Logger.PrintWarning("","Mesh velocity calculation was deactivated. Switching \"calculate_mesh_velocity\" on") + else: + mesh_solver_settings.AddEmptyValue("calculate_mesh_velocity").SetBool(True) + + ## Construct the ALE mesh solver + self.mesh_solver = python_solvers_wrapper_mesh_motion.CreateSolverByParameters(self.model, self.settings["mesh_solver_settings"], self.parallel_type) + KratosMultiphysics.Logger.PrintInfo("PartitionedFSIBaseSolver", "ALE mesh solver construction finished.") + + def _AdvanceInTimeCouplingInterfaces(self, new_time): + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart().CloneTimeStep(new_time) + self._GetFSICouplingInterfaceFluidPositive().GetInterfaceModelPart().CloneTimeStep(new_time) + if self.double_faced_structure: + self._GetFSICouplingInterfaceFluidNegative().GetInterfaceModelPart().CloneTimeStep(new_time) # This method finds the maximum buffer size between mesh, # fluid and structure solvers and sets it to all the solvers. @@ -375,44 +428,62 @@ def _GetAndSetMinimumBufferSize(self): self.mesh_solver.settings["buffer_size"].SetInt(buffer_size) self.structure_solver.settings["buffer_size"].SetInt(buffer_size) - def _GetFluidInterfaceSubmodelPart(self): - # Returns the fluid interface submodelpart that will be used in the residual minimization - return self.fluid_solver.main_model_part.GetSubModelPart(self.fluid_interface_submodelpart_name) + #TODO: SHOULDN'T BE NEEDED AS WE ALWAYS USE THE POSITIVE ONE + # def _GetFluidInterfaceSubmodelPart(self): + # # Returns the fluid interface submodelpart that will be used in the residual minimization + # return self.fluid_solver.main_model_part.GetSubModelPart(self.fluid_interface_submodelpart_name) + + def _InitializeCouplingInterfaces(self): + # Prepare the Dirichlet fluid interfaces + self.__SetFluidInterfaceFixity(self._GetFluidPositiveInterfaceSubmodelPart()) + KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, self._GetFluidPositiveInterfaceSubmodelPart().Nodes) + if self.double_faced_structure: + self.__SetFluidInterfaceFixity(self._GetFluidNegativeInterfaceSubmodelPart()) + KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, self._GetFluidNegativeInterfaceSubmodelPart().Nodes) + + # Prepare the Neumann structure interface + self._SetStructureNeumannCondition() + KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, self._GetStructureInterfaceSubmodelPart().Nodes) + + def __SetFluidInterfaceFixity(self, fluid_interface_submodelpart): + # Fix the VELOCITY, MESH_DISPLACEMENT and MESH_VELOCITY variables in all the fluid interface submodelparts + KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_X, True, fluid_interface_submodelpart.Nodes) + KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_Y, True, fluid_interface_submodelpart.Nodes) + KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_X, True, fluid_interface_submodelpart.Nodes) + KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_Y, True, fluid_interface_submodelpart.Nodes) + if self._GetDomainSize() == 3: + KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_Z, True, fluid_interface_submodelpart.Nodes) + KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_Z, True, fluid_interface_submodelpart.Nodes) def _GetFluidPositiveInterfaceSubmodelPart(self): - mapper_settings = self.settings["coupling_settings"]["mapper_settings"] - - # Get the fluid interface faces submodelpart names - for mapper_id in range(2): - if (mapper_settings[mapper_id]["mapper_face"].GetString() == "Positive"): - pos_face_submodelpart_name = mapper_settings[mapper_id]["fluid_interface_submodelpart_name"].GetString() - # Returns the fluid positive interface submodelpart - return self.fluid_solver.main_model_part.GetSubModelPart(pos_face_submodelpart_name) + positive_interface_name = self.interfaces_dict['fluid_positive'] + return self.model.GetModelPart(positive_interface_name) def _GetFluidNegativeInterfaceSubmodelPart(self): - mapper_settings = self.settings["coupling_settings"]["mapper_settings"] - - # Get the fluid interface faces submodelpart names - for mapper_id in range(2): - if (mapper_settings[mapper_id]["mapper_face"].GetString() == "Negative"): - neg_face_submodelpart_name = mapper_settings[mapper_id]["fluid_interface_submodelpart_name"].GetString() - - # Returns the fluid negative interface submodelpart - return self.fluid_solver.main_model_part.GetSubModelPart(neg_face_submodelpart_name) + negative_interface_name = self.interfaces_dict['fluid_negative'] + return self.model.GetModelPart(negative_interface_name) def _GetStructureInterfaceSubmodelPart(self): # Returns the structure interface submodelpart that will be used in the residual minimization - return self.structure_solver.main_model_part.GetSubModelPart(self.structure_interface_submodelpart_name) + return self.model.GetModelPart(self.__GetStructureInterfaceModelPartName()) - def _GetDomainSize(self): - fluid_domain_size = self.fluid_solver.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] - structure_domain_size = self.structure_solver.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] - - if fluid_domain_size !=structure_domain_size: - raise("ERROR: Solid domain size and fluid domain size are not equal!") + def __GetStructureInterfaceModelPartName(self): + if not hasattr(self, '_structure_interface_submodelpart_name'): + str_int_list = self.settings["coupling_settings"]["structure_interfaces_list"] + if (str_int_list.size() != 1): + raise Exception("FSI embedded solver structure skin must be contained in a unique model part") + self._structure_interface_submodelpart_name = str_int_list[0].GetString() + return self._structure_interface_submodelpart_name - return fluid_domain_size + def _GetDomainSize(self): + if not hasattr(self, '_domain_size'): + fluid_domain_size = self.fluid_solver.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + structure_domain_size = self.structure_solver.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + if fluid_domain_size !=structure_domain_size: + raise("ERROR: Solid domain size and fluid domain size are not equal!") + self._domain_size = fluid_domain_size + return self._domain_size def _ComputeDeltaTime(self): fluid_time_step = self.fluid_solver._ComputeDeltaTime() @@ -426,67 +497,8 @@ def _ComputeDeltaTime(self): return fluid_time_step - def _GetPartitionedFSIUtilities(self): - if (self.domain_size == 2): - return KratosFSI.PartitionedFSIUtilitiesArray2D() - else: - return KratosFSI.PartitionedFSIUtilitiesArray3D() - - def _SetUpMapper(self): - # Recall, to set the INTERFACE flag in both the fluid and solid interface before the mapper construction - search_radius_factor = 2.0 - mapper_max_iterations = 200 - mapper_tolerance = 1e-12 - - mappers_settings = self.settings["coupling_settings"]["mapper_settings"] - - if (mappers_settings.size() == 1): - fluid_submodelpart_name = mappers_settings[0]["fluid_interface_submodelpart_name"].GetString() - structure_submodelpart_name = mappers_settings[0]["structure_interface_submodelpart_name"].GetString() - - fluid_submodelpart = self.fluid_solver.main_model_part.GetSubModelPart(fluid_submodelpart_name) - structure_submodelpart = self.structure_solver.main_model_part.GetSubModelPart(structure_submodelpart_name) - - self.interface_mapper = NonConformant_OneSideMap.NonConformant_OneSideMap(fluid_submodelpart, - structure_submodelpart, - search_radius_factor, - mapper_max_iterations, - mapper_tolerance) - - self.double_faced_structure = False - - elif (mappers_settings.size() == 2): - # Get the fluid interface faces submodelpart names - for mapper_id in range(2): - if (mappers_settings[mapper_id]["mapper_face"].GetString() == "Positive"): - pos_face_submodelpart_name = mappers_settings[mapper_id]["fluid_interface_submodelpart_name"].GetString() - elif (mappers_settings[mapper_id]["mapper_face"].GetString() == "Negative"): - neg_face_submodelpart_name = mappers_settings[mapper_id]["fluid_interface_submodelpart_name"].GetString() - else: - raise Exception("Unique mapper flag has been set but more than one mapper exist in mapper_settings.") - # Get the structure submodelpart name - structure_submodelpart_name = mappers_settings[0]["structure_interface_submodelpart_name"].GetString() - - # Grab the interface submodelparts - pos_fluid_submodelpart = self.fluid_solver.main_model_part.GetSubModelPart(pos_face_submodelpart_name) - neg_fluid_submodelpart = self.fluid_solver.main_model_part.GetSubModelPart(neg_face_submodelpart_name) - structure_submodelpart = self.structure_solver.main_model_part.GetSubModelPart(structure_submodelpart_name) - - self.interface_mapper = NonConformant_OneSideMap.NonConformantTwoFaces_OneSideMap(pos_fluid_submodelpart, - neg_fluid_submodelpart, - structure_submodelpart, - search_radius_factor, - mapper_max_iterations, - mapper_tolerance) - - self.double_faced_structure = True - - else: - raise Exception("Case with more than 2 mappers has not been implemented yet.\n \ - Please, in case you are using single faced immersed bodies, set the skin entities in a unique submodelpart.\n \ - In case you are considering double faced immersed bodies (shells or membranes), set all the positive faces \ - in a unique submodelpart and all the negative ones in another submodelpart.") - + #TODO: THIS MUST BE DONE IN C++ (FSIPartitionedUtils) + #TODO: THINK ABOUT ASSUMING THESE TO BE ALREADY IN THE MPDA (AS THE EMBEDDED DOES) OR TO ALWAYS CREATE THEM (ALSO IN THE EMBEDDED) def _SetStructureNeumannCondition(self): structure_computational_submodelpart = self.structure_solver.GetComputingModelPart() @@ -502,7 +514,7 @@ def _SetStructureNeumannCondition(self): structure_interfaces_list = self.settings["coupling_settings"]["structure_interfaces_list"] for i in range(structure_interfaces_list.size()): interface_submodelpart_name = structure_interfaces_list[i].GetString() - interface_submodelpart_i = self.structure_solver.main_model_part.GetSubModelPart(interface_submodelpart_name) + interface_submodelpart_i = self.model.GetModelPart(interface_submodelpart_name) # Get the number of conditions to be set in each processor local_nodes_number_accumulated = -1 @@ -511,14 +523,14 @@ def _SetStructureNeumannCondition(self): # Create the point load condition aux_count = max_cond_id + local_nodes_number_accumulated - if self.domain_size == 2: + if self._GetDomainSize() == 2: for node in interface_submodelpart_i.GetCommunicator().LocalMesh().Nodes: aux_count+=1 structure_computational_submodelpart.CreateNewCondition("PointLoadCondition2D1N", int(aux_count), [node.Id], self.structure_solver.main_model_part.Properties[0]) - elif self.domain_size == 3: + elif self._GetDomainSize() == 3: for node in interface_submodelpart_i.GetCommunicator().LocalMesh().Nodes: aux_count+=1 structure_computational_submodelpart.CreateNewCondition("PointLoadCondition3D1N", @@ -526,69 +538,292 @@ def _SetStructureNeumannCondition(self): [node.Id], self.structure_solver.main_model_part.Properties[0]) - def _ComputeMeshPredictionSingleFaced(self): - # Get the previous step fluid interface nodal fluxes - keep_sign = False - distribute_load = True - self.interface_mapper.FluidToStructure_VectorMap(KratosMultiphysics.REACTION, - KratosStructural.POINT_LOAD, - keep_sign, - distribute_load) - - # Solve the current step structure problem with the previous step fluid interface nodal fluxes - self.structure_solver.SolveSolutionStep() - - # Map the obtained structure displacement to the fluid interface - keep_sign = True - distribute_load = False - self.interface_mapper.StructureToFluid_VectorMap(KratosMultiphysics.DISPLACEMENT, - KratosMultiphysics.MESH_DISPLACEMENT, - keep_sign, - distribute_load) - - # Solve the mesh problem - self.mesh_solver.InitializeSolutionStep() - self.mesh_solver.Predict() - self.mesh_solver.SolveSolutionStep() - self.mesh_solver.FinalizeSolutionStep() - - def _ComputeMeshPredictionDoubleFaced(self): - # Get the previous step fluid interface nodal fluxes from both positive and negative faces - keep_sign = False - distribute_load = True - self.interface_mapper.PositiveFluidToStructure_VectorMap(KratosMultiphysics.REACTION, - KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE, - keep_sign, - distribute_load) - self.interface_mapper.NegativeFluidToStructure_VectorMap(KratosMultiphysics.REACTION, - KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE, - keep_sign, - distribute_load) - - # Add the two faces contributions to the POINT_LOAD variable - # TODO: Add this to the variables utils - for node in self._GetStructureInterfaceSubmodelPart().Nodes: - pos_face_force = node.GetSolutionStepValue(KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE) - neg_face_force = node.GetSolutionStepValue(KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE) - node.SetSolutionStepValue(KratosStructural.POINT_LOAD, 0, pos_face_force+neg_face_force) - - # Solve the current step structure problem with the previous step fluid interface nodal fluxes - self.structure_solver.SolveSolutionStep() - - # Map the obtained structure displacement to both positive and negative fluid interfaces - keep_sign = True - distribute_load = False - self.interface_mapper.StructureToPositiveFluid_VectorMap(KratosMultiphysics.DISPLACEMENT, - KratosMultiphysics.MESH_DISPLACEMENT, - keep_sign, - distribute_load) - self.interface_mapper.StructureToNegativeFluid_VectorMap(KratosMultiphysics.DISPLACEMENT, - KratosMultiphysics.MESH_DISPLACEMENT, - keep_sign, - distribute_load) - - # Solve the mesh problem - self.mesh_solver.InitializeSolutionStep() - self.mesh_solver.Predict() + def _GetStructureToFluidPositiveInterfaceMapper(self): + if not hasattr(self, '_structure_to_fluid_positive_interface_mapper'): + self._structure_to_fluid_positive_interface_mapper = self._CreateStructureToFluidInterfaceMapper( + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluidPositive().GetInterfaceModelPart()) + return self._structure_to_fluid_positive_interface_mapper + + def _GetStructureToFluidNegativeInterfaceMapper(self): + if not hasattr(self, '_structure_to_fluid_negative_interface_mapper'): + self._structure_to_fluid_negative_interface_mapper = self._CreateStructureToFluidInterfaceMapper( + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluidNegative().GetInterfaceModelPart()) + return self._structure_to_fluid_negative_interface_mapper + + @classmethod + def _CreateStructureToFluidInterfaceMapper(self, structure_interface, fluid_interface): + mapper_params = KratosMultiphysics.Parameters("""{ + "mapper_type": "nearest_element", + "echo_level" : 0 + }""") + structure_to_fluid_interface_mapper = KratosMapping.MapperFactory.CreateMapper( + structure_interface, + fluid_interface, + mapper_params) + + return structure_to_fluid_interface_mapper + + def _GetFSICouplingInterfaceStructure(self): + if not hasattr(self, '_fsi_coupling_interface_structure'): + self._fsi_coupling_interface_structure = self._CreateFSICouplingInterfaceStructure() + return self._fsi_coupling_interface_structure + + def _CreateFSICouplingInterfaceStructure(self): + # Set auxiliary settings + aux_settings = KratosMultiphysics.Parameters( + """{ + "model_part_name": "FSICouplingInterfaceStructure", + "parent_model_part_name": "", + "input_variable_list": ["SURFACE_LOAD"], + "output_variable_list": ["DISPLACEMENT"] + }""") + aux_settings["parent_model_part_name"].SetString(self.interfaces_dict['structure']) + + # Get the convergence accelerator instance (note that it is created in this call) + convergence_accelerator = self._GetConvergenceAccelerator() + + # Construct the FSI coupling interface + fsi_coupling_interface_structure = fsi_coupling_interface.FSICouplingInterface( + self.model, + aux_settings, + convergence_accelerator) + + KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Structure FSI coupling interface created') + + return fsi_coupling_interface_structure + + @classmethod + def _GetFSICouplingInterfaceFluid(self): + err_msg = 'Body-fitted partitioned FSI solver does not implement the \'_GetFSICouplingInterfaceFluid\' method.\n' + err_msg += 'Use \'_GetFSICouplingInterfaceFluidPositive\' as well as \'_GetFSICouplingInterfaceFluidNegative\' if the structure is thin-walled.' + raise Exception(err_msg) + + def _GetFSICouplingInterfaceFluidPositive(self): + if not hasattr(self, '_fsi_coupling_interface_fluid_positive'): + fluid_interface_side = 'fluid_positive' + self._fsi_coupling_interface_fluid_positive = self.__CreateFSICouplingInterfaceFluid(fluid_interface_side) + return self._fsi_coupling_interface_fluid_positive + + def _GetFSICouplingInterfaceFluidNegative(self): + if not hasattr(self, '_fsi_coupling_interface_fluid_negative'): + fluid_interface_side = 'fluid_negative' + self._fsi_coupling_interface_fluid_negative = self.__CreateFSICouplingInterfaceFluid(fluid_interface_side) + return self._fsi_coupling_interface_fluid_negative + + def __CreateFSICouplingInterfaceFluid(self, fluid_interface_side): + # Set auxiliary settings + aux_settings = KratosMultiphysics.Parameters( + """{ + "model_part_name": "", + "parent_model_part_name": "", + "input_variable_list": ["MESH_DISPLACEMENT"], + "output_variable_list": [] + }""") + aux_settings["model_part_name"].SetString("FSICouplingInterface{}".format(fluid_interface_side.capitalize())) + aux_settings["parent_model_part_name"].SetString(self.interfaces_dict[fluid_interface_side]) + aux_settings["output_variable_list"].Append("{}_MAPPED_VECTOR_VARIABLE".format("POSITIVE" if fluid_interface_side == 'fluid_positive' else "NEGATIVE")) + + # Construct the FSI coupling interface + # Note that no convergence accelerator is created in the fluid side + fsi_coupling_interface_fluid = fsi_coupling_interface.FSICouplingInterface( + self.model, + aux_settings) + + KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Fluid {} FSI coupling interface created'.format(fluid_interface_side)) + + return fsi_coupling_interface_fluid + + # This method returns the convergence accelerator. + # If it is not created yet, it calls the _CreateConvergenceAccelerator first + def _GetConvergenceAccelerator(self): + if not hasattr(self, '_convergence_accelerator'): + self._convergence_accelerator = self._CreateConvergenceAccelerator() + return self._convergence_accelerator + + # This method constructs the convergence accelerator coupling utility + def _CreateConvergenceAccelerator(self): + convergence_accelerator = convergence_accelerator_factory.CreateConvergenceAccelerator(self.settings["coupling_settings"]["coupling_strategy_settings"]) + KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Coupling strategy construction finished') + return convergence_accelerator + + def _MapStructureInterfaceDisplacement(self): + # Map the RELAXED_DISPLACEMENT from the structure FSI coupling interface to fluid FSI coupling interface + self._GetStructureToFluidPositiveInterfaceMapper().Map( + KratosMultiphysics.RELAXED_DISPLACEMENT, + KratosMultiphysics.MESH_DISPLACEMENT) + # In case the structure is double faced, we take advantage of the equal positive and negative sides meshes + if self.double_faced_structure: + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( + KratosMultiphysics.MESH_DISPLACEMENT, + KratosMultiphysics.MESH_DISPLACEMENT, + self._GetFSICouplingInterfaceFluidPositive.GetInterfaceModelPart(), + self._GetFSICouplingInterfaceFluidNegative.GetInterfaceModelPart()) + #TODO: Remove as soon as the CopyModelPartNodalVar synchronizes internally + self._GetFSICouplingInterfaceFluidNegative().GetInterfaceModelPart().GetCommunicator().SynchronizeVariable(KratosMultiphysics.MESH_DISPLACEMENT) + + # Update the fluid interface position + self._GetFSICouplingInterfaceFluidPositive().UpdatePosition(KratosMultiphysics.MESH_DISPLACEMENT) + if self.double_faced_structure: + self._GetFSICouplingInterfaceFluidNegative().UpdatePosition(KratosMultiphysics.MESH_DISPLACEMENT) + + def _SolveFluid(self): + # Transfer values from fluid FSI coupling interface to fluid skin + self._GetFSICouplingInterfaceFluidPositive().TransferValuesToFatherModelPart(KratosMultiphysics.MESH_DISPLACEMENT) + if self.double_faced_structure: + self._GetFSICouplingInterfaceFluidNegative().TransferValuesToFatherModelPart(KratosMultiphysics.MESH_DISPLACEMENT) + + # Solve the mesh problem (or moves the interface nodes) + if self.solve_mesh_at_each_iteration: self.mesh_solver.SolveSolutionStep() - self.mesh_solver.FinalizeSolutionStep() + else: + self.mesh_solver.MoveMesh() + + # Impose the structure MESH_VELOCITY in the fluid interface VELOCITY (Lagrangian interface) + KratosMultiphysics.VariableUtils().CopyVariable( + KratosMultiphysics.MESH_VELOCITY, + KratosMultiphysics.VELOCITY, + self._GetFluidPositiveInterfaceSubmodelPart().GetCommunicator().LocalMesh().Nodes) + self._GetFluidPositiveInterfaceSubmodelPart().GetCommunicator().SynchronizeVariable(KratosMultiphysics.VELOCITY) + if self.double_faced_structure: + KratosMultiphysics.VariableUtils().CopyVariable( + KratosMultiphysics.MESH_VELOCITY, + KratosMultiphysics.VELOCITY, + self._GetFluidNegativeInterfaceSubmodelPart().GetCommunicator().LocalMesh().Nodes) + self._GetFluidNegativeInterfaceSubmodelPart().GetCommunicator().SynchronizeVariable(KratosMultiphysics.VELOCITY) + + # Solve fluid problem + self.fluid_solver.SolveSolutionStep() + + def _CalculateFluidInterfaceTraction(self): + # Distribute the REACTION point load + distribution_tolerance = 1.0e-12 + distribution_max_iterations = 500 + + KratosMultiphysics.VariableRedistributionUtility.DistributePointValues( + self._GetFluidPositiveInterfaceSubmodelPart(), + self._GetFluidPositiveInterfaceSubmodelPart().Conditions, + KratosMultiphysics.REACTION, + KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE, + distribution_tolerance, + distribution_max_iterations) + if self.double_faced_structure: + KratosMultiphysics.VariableRedistributionUtility.DistributePointValues( + self._GetFluidNegativeInterfaceSubmodelPart(), + self._GetFluidNegativeInterfaceSubmodelPart().Conditions, + KratosMultiphysics.REACTION, + KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE, + distribution_tolerance, + distribution_max_iterations) + + # Transfer traction values from fluid interface to fluid FSI coupling interface + # NOTE: POSITIVE_MAPPED_VECTOR_VARIABLE is the positive side traction + # NOTE: NEGATIVE_MAPPED_VECTOR_VARIABLE is the negative side traction + self._GetFSICouplingInterfaceFluidPositive().GetValuesFromFatherModelPart(KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE) + if self.double_faced_structure: + self._GetFSICouplingInterfaceFluidNegative().GetValuesFromFatherModelPart(KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE) + + def _MapFluidInterfaceTraction(self): + # Map the distributed REACTION from the fluid FSI coupling interface to structure FSI coupling interface + self._GetStructureToFluidPositiveInterfaceMapper().InverseMap( + self._GetTractionVariable(), + KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE, + KratosMapping.Mapper.SWAP_SIGN) + if self.double_faced_structure: + self._GetStructureToFluidNegativeInterfaceMapper().InverseMap( + self._GetTractionVariable(), + KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE, + KratosMapping.Mapper.ADD_VALUES | KratosMapping.Mapper.SWAP_SIGN) + + # Send the mapped load from the structure FSI coupling interface to the parent one + self._GetFSICouplingInterfaceStructure().TransferValuesToFatherModelPart(self._GetTractionVariable()) + + def _SolveStructure(self): + #TODO: Once we use the distributed (relaxed) traction in the body fitted we can remove this as well as the _SolveStructure in the embedded solver + # Convert distributed traction to point values + KratosMultiphysics.VariableRedistributionUtility.ConvertDistributedValuesToPoint( + self._GetStructureInterfaceSubmodelPart(), + self._GetStructureInterfaceSubmodelPart().Conditions, + self._GetTractionVariable(), + KratosStructural.POINT_LOAD) + + # Solve the structure problem + self.structure_solver.SolveSolutionStep() + + def _ComputeInitialResidual(self): + # Save as RELAXED_DISPLACEMENT the DISPLACEMENT coming from the structure Predict() + # Note that this would be required in order to set the first observation matrices + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( + KratosMultiphysics.DISPLACEMENT, + KratosMultiphysics.RELAXED_DISPLACEMENT, + self._GetStructureInterfaceSubmodelPart(), + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + 0) + #TODO: Remove as soon as the CopyModelPartNodalVar synchronizes internally + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart().GetCommunicator().SynchronizeVariable(KratosMultiphysics.RELAXED_DISPLACEMENT) + + # Update the structure interface position with the DISPLACEMENT values from the predict + self._GetFSICouplingInterfaceStructure().UpdatePosition(KratosMultiphysics.RELAXED_DISPLACEMENT) + + # Map the relaxed displacement from the structure coupling interface to the fluid one + self._MapStructureInterfaceDisplacement() + + # Solve the mesh and fluid problem + self._SolveFluid() + + # Calculate the fluid interface traction from the interface reaction + #TODO: THINK ABOUT COMPUTING THE SUM OF NEGATIVE AND POSITIVE DISTRIBUTED LOAD AND TRANSFER THIS TO THE STRUCTURE (INSTEAD OF PASSING POSITIVE AND NEGATIVE) + self._CalculateFluidInterfaceTraction() + + # Transfer the fluid traction to the structure interface + self._MapFluidInterfaceTraction() + + # Save as RELAXED_TRATION the TRACTION coming from the fluid + # Note that this would be required in order to set the first observation matrices + if self._GetConvergenceAccelerator().IsBlockNewton(): + KratosMultiphysics.VariableUtils().CopyModelPartNodalVar( + self._GetTractionVariable(), + KratosMultiphysics.RELAXED_TRACTION, + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), + 0) + #TODO: Remove as soon as the CopyModelPartNodalVar synchronizes internally + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart().GetCommunicator().SynchronizeVariable(KratosMultiphysics.RELAXED_TRACTION) + + # Directly send the map load from the structure FSI coupling interface to the parent one + self._GetFSICouplingInterfaceStructure().TransferValuesToFatherModelPart(self._GetTractionVariable()) + + # Solve the structure problem + self._SolveStructure() + + # Compute the residual vector + dis_residual_norm = self._GetFSICouplingInterfaceStructure().ComputeResidualVector() + + return dis_residual_norm + + def _CheckFSIConvergence(self, nl_it, residual_norm): + interface_dofs = self._GetPartitionedFSIUtilities().GetInterfaceResidualSize(self._GetStructureInterfaceSubmodelPart()) + normalised_residual = residual_norm/sqrt(interface_dofs) + KratosMultiphysics.Logger.PrintInfo('PartitionedFSIBaseSolver', 'FSI non-linear iteration = {0} |res|/sqrt(nDOFS) = {1}'.format(nl_it, normalised_residual)) + return normalised_residual < self.nl_tol + + def _GetPartitionedFSIUtilities(self): + if not hasattr(self, '_partitioned_fsi_utilities'): + self._partitioned_fsi_utilities = self._CreatePartitionedFSIUtilities() + return self._partitioned_fsi_utilities + + def _CreatePartitionedFSIUtilities(self): + if self._GetDomainSize() == 2: + return KratosFSI.PartitionedFSIUtilitiesArray2D() + elif self._GetDomainSize() == 3: + return KratosFSI.PartitionedFSIUtilitiesArray3D() + else: + raise Exception("Domain size expected to be 2 or 3. Got " + str(self._GetDomainSize())) + + @classmethod + def _GetTractionVariable(self): + #NOTE: No distinction is made between LINE_LOAD and SURFACE_LOAD as this is only used for the redistribution + #NOTE: Hence, this has only an auxiliary use as the traction will be converted to point load prior to the structure solve + #TODO: Use LINE_LOAD in 2D and SURFACE_LOAD in 3D when using distributed loads conditions + return KratosStructural.SURFACE_LOAD diff --git a/applications/FSIApplication/python_scripts/partitioned_fsi_dirichlet_neumann_solver.py b/applications/FSIApplication/python_scripts/partitioned_fsi_dirichlet_neumann_solver.py deleted file mode 100755 index ebcaad7ec669..000000000000 --- a/applications/FSIApplication/python_scripts/partitioned_fsi_dirichlet_neumann_solver.py +++ /dev/null @@ -1,223 +0,0 @@ -from __future__ import print_function, absolute_import, division # makes KratosMultiphysics backward compatible with python 2.6 and 2.7 - -# Importing the Kratos Library -import KratosMultiphysics - -# Import applications -import KratosMultiphysics.StructuralMechanicsApplication as KratosStructural - -# Import base class file -from KratosMultiphysics.FSIApplication import partitioned_fsi_base_solver - -def CreateSolver(model, project_parameters): - return PartitionedFSIDirichletNeumannSolver(model, project_parameters) - -class PartitionedFSIDirichletNeumannSolver(partitioned_fsi_base_solver.PartitionedFSIBaseSolver): - def __init__(self, model, project_parameters): - super(PartitionedFSIDirichletNeumannSolver, self).__init__(model, project_parameters) - KratosMultiphysics.Logger.PrintInfo("::[PartitionedFSIDirichletNeumannSolver]::", "Solver construction finished.") - - @classmethod - def GetDefaultParameters(cls): - - this_defaults = KratosMultiphysics.Parameters("""{ - "coupling_scheme": "dirichlet_neumann" - }""") - - this_defaults.AddMissingParameters(super().GetDefaultParameters()) - return this_defaults - - def Initialize(self): - # Get the domain size - self.domain_size = self._GetDomainSize() - - # Get the partitioned FSI utilities - self.partitioned_fsi_utilities = self._GetPartitionedFSIUtilities() - - # Python structure solver initialization - self.structure_solver.Initialize() - - # Ensure that the fluid reaction fluxes are computed if D-N scheme is considered - if self.fluid_solver.settings["compute_reactions"].GetBool() == False: - self.fluid_solver.settings["compute_reactions"].SetBool(True) - - # Python fluid solver initialization - self.fluid_solver.Initialize() - - # Python mesh solver initialization - self.mesh_solver.Initialize() - - # Initialize the Dirichlet-Neumann interface - self._InitializeDirichletNeumannInterface() - - # Construct the interface mapper - self._SetUpMapper() - - # Set the Neumann B.C. in the structure interface - self._SetStructureNeumannCondition() #TODO change when the interface is able to correctly transfer distributed forces - - # Initialize the iteration value vector - self._InitializeIterationValueVector() - - # Compute the fluid domain NODAL_AREA values (required as weight in the residual norm computation) - KratosMultiphysics.CalculateNodalAreaProcess(self.fluid_solver.GetComputingModelPart(), self.domain_size).Execute() - - # Coupling utility initialization - # The _GetConvergenceAccelerator is supposed to construct the convergence accelerator in here - self._GetConvergenceAccelerator().Initialize() - - def _InitializeIterationValueVector(self): - # Note that the FSI problem is defined in terms of the fluid interface - # Besides, one of the two interfaces is considered for the residual vector computation - # in case a shell structure is analised. This is due to the fact that the same mesh_solver - # displacement is map to both fluid sides. - - # Initialize the iteration value for the residual computation - fluid_interface_residual_size = self.partitioned_fsi_utilities.GetInterfaceResidualSize(self._GetFluidInterfaceSubmodelPart()) - self.iteration_value = KratosMultiphysics.Vector(fluid_interface_residual_size) - for i in range(0,fluid_interface_residual_size): - self.iteration_value[i] = 0.0 - - def _InitializeDirichletNeumannInterface(self): - # Initialize Dirichlet fluid interface - coupling_settings = self.settings["coupling_settings"] - num_fl_interfaces = coupling_settings["fluid_interfaces_list"].size() - for fl_interface_id in range(num_fl_interfaces): - fl_interface_name = coupling_settings["fluid_interfaces_list"][fl_interface_id].GetString() - fl_interface_submodelpart = self.fluid_solver.main_model_part.GetSubModelPart(fl_interface_name) - - # Fix the VELOCITY, MESH_DISPLACEMENT and MESH_VELOCITY variables in all the fluid interface submodelparts - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_X, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_Y, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_Z, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_X, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_Y, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_Z, True, fl_interface_submodelpart.Nodes) - - # Set the interface flag - KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, fl_interface_submodelpart.Nodes) - - # Initialize Neumann structure interface - num_str_interfaces = coupling_settings["structure_interfaces_list"].size() - for str_interface_id in range(num_str_interfaces): - str_interface_name = coupling_settings["structure_interfaces_list"][str_interface_id].GetString() - str_interface_submodelpart = self.structure_solver.main_model_part.GetSubModelPart(str_interface_name) - - # Set the interface flag - KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, str_interface_submodelpart.Nodes) - - def _SolveMeshAndFluid(self): - # Set the iteration_value displacement as MESH_DISPLACEMENT - coupling_settings = self.settings["coupling_settings"] - num_fl_interfaces = coupling_settings["fluid_interfaces_list"].size() - for fl_interface_id in range(num_fl_interfaces): - fl_interface_name = coupling_settings["fluid_interfaces_list"][fl_interface_id].GetString() - fl_interface_submodelpart = self.fluid_solver.main_model_part.GetSubModelPart(fl_interface_name) - self.partitioned_fsi_utilities.UpdateInterfaceValues( - fl_interface_submodelpart, - KratosMultiphysics.MESH_DISPLACEMENT, - self.iteration_value) - - # Solve the mesh problem (or moves the interface nodes) - if self.solve_mesh_at_each_iteration: - self.mesh_solver.SolveSolutionStep() - else: - self.mesh_solver.MoveMesh() - - # Impose the structure MESH_VELOCITY and MESH_ACCELERATION in the fluid interface VELOCITY and ACCELERATION - KratosMultiphysics.VariableUtils().CopyVectorVar( - KratosMultiphysics.MESH_VELOCITY, - KratosMultiphysics.VELOCITY, - self._GetFluidInterfaceSubmodelPart().GetCommunicator().LocalMesh().Nodes) - self._GetFluidInterfaceSubmodelPart().GetCommunicator().SynchronizeVariable(KratosMultiphysics.VELOCITY) - - # Solve fluid problem - self.fluid_solver.SolveSolutionStep() - - def _SolveStructureSingleFaced(self): - # Transfer fluid reaction to solid interface - keep_sign = False - distribute_load = True - self.interface_mapper.FluidToStructure_VectorMap(KratosMultiphysics.REACTION, - KratosStructural.POINT_LOAD, - keep_sign, - distribute_load) - - # Solve the structure problem - self.structure_solver.SolveSolutionStep() - - def _SolveStructureDoubleFaced(self): - # Transfer fluid reaction from both sides to the structure interface - keep_sign = False - distribute_load = True - self.interface_mapper.PositiveFluidToStructure_VectorMap(KratosMultiphysics.REACTION, - KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE, - keep_sign, - distribute_load) - self.interface_mapper.NegativeFluidToStructure_VectorMap(KratosMultiphysics.REACTION, - KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE, - keep_sign, - distribute_load) - - # Add the two faces contributions to the POINT_LOAD variable - # TODO: Add this to the variables utils - for node in self._GetStructureInterfaceSubmodelPart().Nodes: - pos_face_force = node.GetSolutionStepValue(KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE) - neg_face_force = node.GetSolutionStepValue(KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE) - node.SetSolutionStepValue(KratosStructural.POINT_LOAD, 0, pos_face_force+neg_face_force) - - # Solve the structure problem - self.structure_solver.SolveSolutionStep() - - def _ComputeDisplacementResidualSingleFaced(self): - # Project the structure velocity onto the fluid interface - keep_sign = True - distribute_load = False - self.interface_mapper.StructureToFluid_VectorMap(KratosMultiphysics.DISPLACEMENT, - KratosMultiphysics.VECTOR_PROJECTED, - keep_sign, - distribute_load) - - # Compute the fluid interface residual vector by means of the VECTOR_PROJECTED variable - # Besides, its norm is stored within the ProcessInfo. - disp_residual = KratosMultiphysics.Vector(self.partitioned_fsi_utilities.GetInterfaceResidualSize(self._GetFluidInterfaceSubmodelPart())) - self.partitioned_fsi_utilities.ComputeInterfaceResidualVector( - self._GetFluidInterfaceSubmodelPart(), - KratosMultiphysics.MESH_DISPLACEMENT, - KratosMultiphysics.VECTOR_PROJECTED, - KratosMultiphysics.FSI_INTERFACE_RESIDUAL, - disp_residual, - "nodal", - KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM) - - return disp_residual - - def _ComputeDisplacementResidualDoubleFaced(self): - # Project the structure velocity onto the fluid interface - keep_sign = True - distribute_load = False - #TODO: One of these mappings is not needed. At the moment both are performed to ensure that - # the _GetFluidInterfaceSubmodelPart(), which is the one used to compute the interface residual, - # gets the structure DISPLACEMENT. Think a way to properly identify the reference fluid interface. - self.interface_mapper.StructureToPositiveFluid_VectorMap(KratosMultiphysics.DISPLACEMENT, - KratosMultiphysics.VECTOR_PROJECTED, - keep_sign, - distribute_load) - self.interface_mapper.StructureToNegativeFluid_VectorMap(KratosMultiphysics.DISPLACEMENT, - KratosMultiphysics.VECTOR_PROJECTED, - keep_sign, - distribute_load) - - # Compute the fluid interface residual vector by means of the VECTOR_PROJECTED variable - # Besides, its norm is stored within the ProcessInfo. - disp_residual = KratosMultiphysics.Vector(self.partitioned_fsi_utilities.GetInterfaceResidualSize(self._GetFluidInterfaceSubmodelPart())) - self.partitioned_fsi_utilities.ComputeInterfaceResidualVector( - self._GetFluidInterfaceSubmodelPart(), - KratosMultiphysics.MESH_DISPLACEMENT, - KratosMultiphysics.VECTOR_PROJECTED, - KratosMultiphysics.FSI_INTERFACE_MESH_RESIDUAL, - disp_residual, - "nodal", - KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM) - - return disp_residual diff --git a/applications/FSIApplication/python_scripts/python_solvers_wrapper_fsi.py b/applications/FSIApplication/python_scripts/python_solvers_wrapper_fsi.py index 711c55af68e4..4c5a6e624a06 100644 --- a/applications/FSIApplication/python_scripts/python_solvers_wrapper_fsi.py +++ b/applications/FSIApplication/python_scripts/python_solvers_wrapper_fsi.py @@ -18,7 +18,7 @@ def CreateSolverByParameters(model, solver_settings, parallelism): if (parallelism == "OpenMP"): if (solver_type == "Partitioned" or solver_type == "partitioned"): if (coupling_scheme == "DirichletNeumann" or coupling_scheme == "dirichlet_neumann"): - solver_module_name = "partitioned_fsi_dirichlet_neumann_solver" + solver_module_name = "partitioned_fsi_base_solver" else: err_msg = 'Requested coupling_scheme: ' + coupling_scheme + ' is not available.' raise Exception(err_msg) @@ -35,7 +35,7 @@ def CreateSolverByParameters(model, solver_settings, parallelism): elif (parallelism == "MPI"): if (solver_type == "Partitioned" or solver_type == "partitioned"): if (coupling_scheme == "DirichletNeumann" or coupling_scheme == "dirichlet_neumann"): - solver_module_name = "trilinos_partitioned_fsi_dirichlet_neumann_solver" + solver_module_name = "trilinos_partitioned_fsi_base_solver" else: err_msg = 'Requested coupling_scheme: ' + coupling_scheme + ' is not available.' raise Exception(err_msg) diff --git a/applications/FSIApplication/python_scripts/trilinos_partitioned_fsi_base_solver.py b/applications/FSIApplication/python_scripts/trilinos_partitioned_fsi_base_solver.py index 3f39e0dea9a4..7e232764d39c 100644 --- a/applications/FSIApplication/python_scripts/trilinos_partitioned_fsi_base_solver.py +++ b/applications/FSIApplication/python_scripts/trilinos_partitioned_fsi_base_solver.py @@ -2,6 +2,7 @@ # Import utilities from KratosMultiphysics.FSIApplication import convergence_accelerator_factory # Import the FSI convergence accelerator factory +from KratosMultiphysics.FSIApplication import fsi_coupling_interface # Importing the Kratos Library import KratosMultiphysics @@ -29,33 +30,9 @@ def GetDefaultParameters(cls): this_defaults = KratosMultiphysics.Parameters("""{ "parallel_type": "MPI" }""") - this_defaults.AddMissingParameters(super(TrilinosPartitionedFSIBaseSolver, cls).GetDefaultParameters()) + this_defaults.AddMissingParameters(super().GetDefaultParameters()) return this_defaults - def AddVariables(self): - ## Structure variables addition - # Standard CSM variables addition - self.structure_solver.AddVariables() - - ## Fluid variables addition - # Standard CFD variables addition - self.fluid_solver.AddVariables() - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.FORCE) - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.MESH_ACCELERATION) # TODO: This should be added in the mesh solvers - # Mesh solver variables addition - self.mesh_solver.AddVariables() - - ## FSIApplication variables addition - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VAUX_EQ_TRACTION) - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VECTOR_PROJECTED) - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.FSI_INTERFACE_RESIDUAL) - self.fluid_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.FSI_INTERFACE_MESH_RESIDUAL) - - self.structure_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VAUX_EQ_TRACTION) - self.structure_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VECTOR_PROJECTED) - self.structure_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.POSITIVE_MAPPED_VECTOR_VARIABLE) - self.structure_solver.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NEGATIVE_MAPPED_VECTOR_VARIABLE) - def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = self._CreateEpetraCommunicator() @@ -65,184 +42,61 @@ def _CreateEpetraCommunicator(self): return KratosTrilinos.CreateCommunicator() def _CreateConvergenceAccelerator(self): + """ Create the MPI parallel convergence accelerator and assign it to the structure FSI coupling interface""" + # Create the MPI parallel convergence accelerator convergence_accelerator = convergence_accelerator_factory.CreateTrilinosConvergenceAccelerator( - self._GetFluidInterfaceSubmodelPart(), + self._GetFSICouplingInterfaceStructure().GetInterfaceModelPart(), self._GetEpetraCommunicator(), self.settings["coupling_settings"]["coupling_strategy_settings"]) - KratosMultiphysics.Logger.PrintInfo("::[TrilinosPartitionedFSIBaseSolver]::", "Coupling strategy construction finished.") + # Assign the new convergence accelerator to the structure FSI coupling interface + self._GetFSICouplingInterfaceStructure().SetConvergenceAccelerator(convergence_accelerator) + KratosMultiphysics.Logger.PrintInfo('TrilinosPartitionedFSIBaseSolver', 'Coupling strategy construction finished.') return convergence_accelerator - def _GetPartitionedFSIUtilities(self): - if (self.domain_size == 2): + def _CreateFSICouplingInterfaceStructure(self): + """Create the structure FSI coupling interface + + Create the structure FSI coupling interface with a default MPI convergence accelerator + The final convergence accelerator will be assigned to the structure FSI coupling interface in the _CreateConvergenceAccelerator + This is required since the MPI parallel convergence accelerators require the residual minimization model part to be instantiated + """ + # Set auxiliary settings + aux_settings = KratosMultiphysics.Parameters( + """{ + "model_part_name": "FSICouplingInterfaceStructure", + "parent_model_part_name": "", + "input_variable_list": ["SURFACE_LOAD"], + "output_variable_list": ["DISPLACEMENT"] + }""") + aux_settings["parent_model_part_name"].SetString(self.interfaces_dict['structure']) + + # Construct the FSI coupling interface + fsi_coupling_interface_structure = fsi_coupling_interface.FSICouplingInterface( + self.model, + aux_settings, + KratosTrilinos.TrilinosConvergenceAccelerator()) + + KratosMultiphysics.Logger.PrintInfo('PartitionedEmbeddedFSIBaseSolver', 'Structure FSI coupling interface created') + + return fsi_coupling_interface_structure + + def _CreatePartitionedFSIUtilities(self): + if self._GetDomainSize() == 2: return KratosTrilinos.TrilinosPartitionedFSIUtilitiesArray2D(self._GetEpetraCommunicator()) - else: + elif self._GetDomainSize() == 3: return KratosTrilinos.TrilinosPartitionedFSIUtilitiesArray3D(self._GetEpetraCommunicator()) + else: + raise Exception("Domain size expected to be 2 or 3. Got " + str(self._GetDomainSize())) - ### TODO: SUBSTITUTE IN THIS METHOD THE OLD MAPPER BY THE ONE IN THE FSI APPLICATION - def _SetUpMapper(self): - mapper_settings = self.settings["coupling_settings"]["mapper_settings"] - - if (mapper_settings.size() == 1): - fluid_submodelpart_name = mapper_settings[0]["fluid_interface_submodelpart_name"].GetString() - structure_submodelpart_name = mapper_settings[0]["structure_interface_submodelpart_name"].GetString() - - mapper_project_parameters = KratosMultiphysics.Parameters("""{ - "mapper_type" : "", - "interface_submodel_part_origin" : "", - "interface_submodel_part_destination" : "" - }""") - mapper_project_parameters["mapper_type"].SetString("nearest_element") - mapper_project_parameters["interface_submodel_part_origin"].SetString(fluid_submodelpart_name) - mapper_project_parameters["interface_submodel_part_destination"].SetString(structure_submodelpart_name) - - self.interface_mapper = KratosMapping.MapperFactory.CreateMPIMapper(self.fluid_solver.main_model_part, - self.structure_solver.main_model_part, - mapper_project_parameters) - - self.double_faced_structure = False - - elif (mapper_settings.size() == 2): - # Get the fluid interface faces submodelpart names - for mapper_id in range(2): - if (mapper_settings[mapper_id]["mapper_face"].GetString() == "Positive"): - pos_face_submodelpart_name = mapper_settings[mapper_id]["fluid_interface_submodelpart_name"].GetString() - elif (mapper_settings[mapper_id]["mapper_face"].GetString() == "Negative"): - neg_face_submodelpart_name = mapper_settings[mapper_id]["fluid_interface_submodelpart_name"].GetString() - else: - raise Exception("Unique mapper flag has been set but more than one mapper exist in mapper_settings.") - - # Get the structure submodelpart name - structure_submodelpart_name = mapper_settings[0]["structure_interface_submodelpart_name"].GetString() - - # Set the positive side fluid interface mapper - pos_mapper_project_parameters = KratosMultiphysics.Parameters("""{ - "mapper_type" : "", - "interface_submodel_part_origin" : "", - "interface_submodel_part_destitnation" : "" - }""") - pos_mapper_project_parameters["mapper_type"].SetString("nearest_element") - pos_mapper_project_parameters["interface_submodel_part_origin"].SetString(pos_face_submodelpart_name) - pos_mapper_project_parameters["interface_submodel_part_destination"].SetString(structure_submodelpart_name) - - self.pos_interface_mapper = KratosMapping.MapperFactory.CreateMPIMapper(self.fluid_solver.main_model_part, - self.structure_solver.main_model_part, - pos_mapper_project_parameters) - - # Set the positive side fluid interface mapper - neg_mapper_project_parameters = KratosMultiphysics.Parameters("""{ - "mapper_type" : "", - "interface_submodel_part_origin" : "", - "interface_submodel_part_destitnation" : "" - }""") - neg_mapper_project_parameters["mapper_type"].SetString("nearest_element") - neg_mapper_project_parameters["interface_submodel_part_origin"].SetString(neg_face_submodelpart_name) - neg_mapper_project_parameters["interface_submodel_part_destination"].SetString(structure_submodelpart_name) - - self.neg_interface_mapper = KratosMapping.MapperFactory.CreateMPIMapper(self.fluid_solver.main_model_part, - self.structure_solver.main_model_part, - neg_mapper_project_parameters) - - self.double_faced_structure = True + @classmethod + def _CreateStructureToFluidInterfaceMapper(self, structure_interface, fluid_interface): + mapper_params = KratosMultiphysics.Parameters("""{ + "mapper_type": "nearest_element", + "echo_level" : 0 + }""") + structure_to_fluid_interface_mapper = KratosMapping.MapperFactory.CreateMPIMapper( + structure_interface, + fluid_interface, + mapper_params) - else: - raise Exception("Case with more than 2 mappers has not been implemented yet.\n \ - Please, in case you are using single faced immersed bodies, set the skin entities in a unique submodelpart.\n \ - In case you are considering double faced immersed bodies (shells or membranes), set all the positive faces \ - in a unique submodelpart and all the negative ones in another submodelpart.") - - def _ComputeMeshPredictionSingleFaced(self): - step = self.fluid_solver.main_model_part.ProcessInfo[KratosMultiphysics.STEP] - KratosMultiphysics.Logger.PrintInfo("Computing time step ",str(step)," prediction...") - - # Set the redistribution settings - redistribution_tolerance = 1e-8 - redistribution_max_iters = 200 - - # Convert the nodal reaction to traction loads before transfering - KratosMultiphysics.VariableRedistributionUtility.DistributePointValues( - self._GetFluidInterfaceSubmodelPart(), - KratosMultiphysics.REACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - redistribution_tolerance, - redistribution_max_iters) - - # Transfer fluid tractions to the structure interface - self.interface_mapper.Map(KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMapping.Mapper.SWAP_SIGN) - - # Convert the transferred traction loads to point loads - KratosMultiphysics.VariableRedistributionUtility.ConvertDistributedValuesToPoint( - self._GetStructureInterfaceSubmodelPart(), - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosStructural.POINT_LOAD) - - # Solve the current step structure problem with the previous step fluid interface nodal fluxes - is_converged = self.structure_solver.SolveSolutionStep() - if not is_converged: - KratosMultiphysics.Logger.PrintWarningInfo("Mesh prediction structure solver did not converge.") - - # Map the obtained structure displacement to the fluid interface - self.interface_mapper.InverseMap(KratosMultiphysics.MESH_DISPLACEMENT, KratosMultiphysics.DISPLACEMENT) - - # Solve the mesh problem - self.mesh_solver.InitializeSolutionStep() - self.mesh_solver.Predict() - self.mesh_solver.SolveSolutionStep() - self.mesh_solver.FinalizeSolutionStep() - - KratosMultiphysics.Logger.PrintInfo("Mesh prediction computed.") - - def _ComputeMeshPredictionDoubleFaced(self): - step = self.fluid_solver.main_model_part.ProcessInfo[KratosMultiphysics.STEP] - KratosMultiphysics.Logger.PrintInfo("Computing time step ",str(step)," prediction...") - - # Set the redistribution settings - redistribution_tolerance = 1e-8 - redistribution_max_iters = 200 - - # Convert the nodal reaction to traction loads before transfering - KratosMultiphysics.VariableRedistributionUtility.DistributePointValues( - self._GetFluidPositiveInterfaceSubmodelPart(), - KratosMultiphysics.REACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - redistribution_tolerance, - redistribution_max_iters) - - KratosMultiphysics.VariableRedistributionUtility.DistributePointValues( - self._GetFluidNegativeInterfaceSubmodelPart(), - KratosMultiphysics.REACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - redistribution_tolerance, - redistribution_max_iters) - - # Transfer fluid tractions to the structure interface - # Note that the ADD_VALUES flag is only specified for the second mapper - # since we want the first mapper to overwrite the existent values - self.pos_interface_mapper.Map(KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMapping.Mapper.SWAP_SIGN) - - self.neg_interface_mapper.Map(KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMapping.Mapper.SWAP_SIGN | KratosMapping.Mapper.ADD_VALUES) - - # Convert the transferred traction loads to point loads - KratosMultiphysics.VariableRedistributionUtility.ConvertDistributedValuesToPoint( - self._GetStructureInterfaceSubmodelPart(), - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosStructural.POINT_LOAD) - - # Solve the current step structure problem with the previous step fluid interface nodal fluxes - is_converged = self.structure_solver.SolveSolutionStep() - if not is_converged: - KratosMultiphysics.Logger.PrintWarningInfo("Mesh prediction structure solver did not converge.") - - # Map the obtained structure displacement to the fluid interface - self.pos_interface_mapper.InverseMap(KratosMultiphysics.MESH_DISPLACEMENT, KratosMultiphysics.DISPLACEMENT) - self.neg_interface_mapper.InverseMap(KratosMultiphysics.MESH_DISPLACEMENT, KratosMultiphysics.DISPLACEMENT) - - # Solve the mesh problem - self.mesh_solver.Solve() - - KratosMultiphysics.Logger.PrintInfo("Mesh prediction computed.") + return structure_to_fluid_interface_mapper diff --git a/applications/FSIApplication/python_scripts/trilinos_partitioned_fsi_dirichlet_neumann_solver.py b/applications/FSIApplication/python_scripts/trilinos_partitioned_fsi_dirichlet_neumann_solver.py deleted file mode 100644 index a360e2fda6d2..000000000000 --- a/applications/FSIApplication/python_scripts/trilinos_partitioned_fsi_dirichlet_neumann_solver.py +++ /dev/null @@ -1,244 +0,0 @@ -from __future__ import print_function, absolute_import, division # makes KratosMultiphysics backward compatible with python 2.6 and 2.7 - -# Importing the Kratos Library -import KratosMultiphysics - -# Import applications -import KratosMultiphysics.TrilinosApplication as KratosTrilinos -import KratosMultiphysics.MappingApplication as KratosMapping -import KratosMultiphysics.StructuralMechanicsApplication as KratosStructural - -# Import base class file -from KratosMultiphysics.FSIApplication import trilinos_partitioned_fsi_base_solver # Base class file - -def CreateSolver(model, project_parameters): - return TrilinosPartitionedFSIDirichletNeumannSolver(model, project_parameters) - -class TrilinosPartitionedFSIDirichletNeumannSolver(trilinos_partitioned_fsi_base_solver.TrilinosPartitionedFSIBaseSolver): - def __init__(self, model, project_parameters): - super(TrilinosPartitionedFSIDirichletNeumannSolver, self).__init__(model, project_parameters) - KratosMultiphysics.Logger.PrintInfo("::[TrilinosPartitionedFSIDirichletNeumannSolver]::", "Solver construction finished.") - - @classmethod - def GetDefaultParameters(cls): - """This function returns the default-settings used by this class - """ - this_defaults = KratosMultiphysics.Parameters("""{ - "coupling_scheme": "dirichlet_neumann" - }""") - this_defaults.AddMissingParameters(super(TrilinosPartitionedFSIDirichletNeumannSolver, cls).GetDefaultParameters()) - return this_defaults - - def Initialize(self): - # Set the Trilinos space - self.trilinos_space = KratosTrilinos.TrilinosSparseSpace() - - # Get the domain size - self.domain_size = self._GetDomainSize() - - # Get the partitioned FSI utilities - self.partitioned_fsi_utilities = self._GetPartitionedFSIUtilities() - - # Python structure solver initialization - self.structure_solver.Initialize() - - # Ensure that the fluid reaction fluxes are computed if D-N scheme is considered - if self.fluid_solver.settings["compute_reactions"].GetBool() == False: - self.fluid_solver.settings["compute_reactions"].SetBool(True) - - # Python fluid solver initialization - self.fluid_solver.Initialize() - - # Python mesh solver initialization - self.mesh_solver.Initialize() - - # Initialize the Dirichlet-Neumann interface - self._InitializeDirichletNeumannInterface() - - # Construct the interface mapper - self._SetUpMapper() - - # Set the Neumann B.C. in the structure interface - self._SetStructureNeumannCondition() #TODO change when the interface is able to correctly transfer distributed forces - - # Initialize the iteration value for the residual computation, which is defined in terms of the fluid interface - # In case a shell structure is analised, only one of the two interfaces is considered for the residual vector computation - # This is due to the fact that the same mesh_solver displacement is map to both fluid sides. - self.iteration_value = self.partitioned_fsi_utilities.SetUpInterfaceVector(self._GetFluidInterfaceSubmodelPart()) - - # Compute the fluid domain NODAL_AREA values (required as weight in the residual norm computation) - KratosMultiphysics.CalculateNodalAreaProcess(self.fluid_solver.GetComputingModelPart(), self.domain_size).Execute() - - # Coupling utility initialization - # The _GetConvergenceAccelerator is supposed to construct the convergence accelerator in here - self._GetConvergenceAccelerator().Initialize() - - def _InitializeDirichletNeumannInterface(self): - # Initialize Dirichlet fluid interface - fluid_interfaces_list = self.settings["coupling_settings"]["fluid_interfaces_list"] - for fl_interface_id in range(fluid_interfaces_list.size()): - fl_interface_name = fluid_interfaces_list[fl_interface_id].GetString() - fl_interface_submodelpart = self.fluid_solver.main_model_part.GetSubModelPart(fl_interface_name) - - # Fix the VELOCITY, MESH_DISPLACEMENT and MESH_VELOCITY variables in all the fluid interface submodelparts - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_X, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_Y, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_X, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_Y, True, fl_interface_submodelpart.Nodes) - if (self.domain_size == 3): - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.VELOCITY_Z, True, fl_interface_submodelpart.Nodes) - KratosMultiphysics.VariableUtils().ApplyFixity(KratosMultiphysics.MESH_DISPLACEMENT_Z, True, fl_interface_submodelpart.Nodes) - - # Set the interface flag - KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, fl_interface_submodelpart.Nodes) - - # Initialize Neumann structure interface - structure_interfaces_list = self.settings["coupling_settings"]["structure_interfaces_list"] - for str_interface_id in range(structure_interfaces_list.size()): - str_interface_name = structure_interfaces_list[str_interface_id].GetString() - str_interface_submodelpart = self.structure_solver.main_model_part.GetSubModelPart(str_interface_name) - - # Set the interface flag - KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, str_interface_submodelpart.Nodes) - - def _SolveMeshAndFluid(self): - # Set the iteration_value displacement as MESH_DISPLACEMENT - coupling_settings = self.settings["coupling_settings"] - num_fl_interfaces = coupling_settings["fluid_interfaces_list"].size() - for fl_interface_id in range(num_fl_interfaces): - fl_interface_name = coupling_settings["fluid_interfaces_list"][fl_interface_id].GetString() - fl_interface_submodelpart = self.fluid_solver.main_model_part.GetSubModelPart(fl_interface_name) - self.partitioned_fsi_utilities.UpdateInterfaceValues( - fl_interface_submodelpart, - KratosMultiphysics.MESH_DISPLACEMENT, - self.iteration_value) - - # Solve the mesh problem (or moves the interface nodes) - if self.solve_mesh_at_each_iteration: - self.mesh_solver.SolveSolutionStep() - else: - self.mesh_solver.MoveMesh() - - # Impose the structure MESH_VELOCITY and MESH_ACCELERATION in the fluid interface VELOCITY and ACCELERATION - KratosMultiphysics.VariableUtils().CopyVectorVar( - KratosMultiphysics.MESH_VELOCITY, - KratosMultiphysics.VELOCITY, - self._GetFluidInterfaceSubmodelPart().GetCommunicator().LocalMesh().Nodes) - self._GetFluidInterfaceSubmodelPart().GetCommunicator().SynchronizeVariable(KratosMultiphysics.VELOCITY) - - # Solve fluid problem - self.fluid_solver.SolveSolutionStep() - - def _SolveStructureSingleFaced(self): - # Set the redistribution settings - redistribution_tolerance = 1e-8 - redistribution_max_iters = 200 - - # Convert the nodal reaction to traction loads before transfering - KratosMultiphysics.VariableRedistributionUtility.DistributePointValues( - self._GetFluidInterfaceSubmodelPart(), - KratosMultiphysics.REACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - redistribution_tolerance, - redistribution_max_iters) - - # Transfer fluid tractions to the structure interface - self.interface_mapper.Map(KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMapping.Mapper.SWAP_SIGN) - - # Convert the transferred traction loads to point loads - KratosMultiphysics.VariableRedistributionUtility.ConvertDistributedValuesToPoint( - self._GetStructureInterfaceSubmodelPart(), - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosStructural.POINT_LOAD) - - # Solve the structure problem - is_converged = self.structure_solver.SolveSolutionStep() - if not is_converged: - KratosMultiphysics.Logger.PrintWarning("Structure solver did not converge.") - - def _SolveStructureDoubleFaced(self): - # Set the redistribution settings - redistribution_tolerance = 1e-8 - redistribution_max_iters = 200 - - # Convert the nodal reaction to traction loads before transfering - KratosMultiphysics.VariableRedistributionUtility.DistributePointValues( - self._GetFluidPositiveInterfaceSubmodelPart(), - KratosMultiphysics.REACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - redistribution_tolerance, - redistribution_max_iters) - - KratosMultiphysics.VariableRedistributionUtility.DistributePointValues( - self._GetFluidNegativeInterfaceSubmodelPart(), - KratosMultiphysics.REACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - redistribution_tolerance, - redistribution_max_iters) - - # Transfer fluid tractions to the structure interface - # Note that the ADD_VALUES flag is only specified for the second mapper - # since we want the first mapper to overwrite the existent values - self.pos_interface_mapper.Map(KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMapping.Mapper.SWAP_SIGN) - - # Transfer fluid tractions to the structure interface - self.neg_interface_mapper.Map(KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosMapping.Mapper.SWAP_SIGN | KratosMapping.Mapper.ADD_VALUES) - - # Convert the transferred traction loads to point loads - KratosMultiphysics.VariableRedistributionUtility.ConvertDistributedValuesToPoint( - self._GetStructureInterfaceSubmodelPart(), - KratosMultiphysics.VAUX_EQ_TRACTION, - KratosStructural.POINT_LOAD) - - # Solve the structure problem - is_converged = self.structure_solver.SolveSolutionStep() - if not is_converged: - KratosMultiphysics.Logger.PrintWarning("Structure solver did not converge.") - - def _ComputeDisplacementResidualSingleFaced(self): - # Project the structure displacement onto the fluid interface - self.interface_mapper.InverseMap(KratosMultiphysics.VECTOR_PROJECTED, - KratosMultiphysics.DISPLACEMENT) - - # Compute the fluid interface residual vector by means of the VECTOR_PROJECTED variable - # Besides, its norm is stored within the ProcessInfo. - disp_residual = self.partitioned_fsi_utilities.SetUpInterfaceVector(self._GetFluidInterfaceSubmodelPart()) - self.partitioned_fsi_utilities.ComputeInterfaceResidualVector( - self._GetFluidInterfaceSubmodelPart(), - KratosMultiphysics.MESH_DISPLACEMENT, - KratosMultiphysics.VECTOR_PROJECTED, - KratosMultiphysics.FSI_INTERFACE_RESIDUAL, - disp_residual, - "nodal", - KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM) - - return disp_residual - - def _ComputeDisplacementResidualDoubleFaced(self): - # Project the structure displacement onto the fluid positive interface - self.pos_interface_mapper.InverseMap(KratosMultiphysics.VECTOR_PROJECTED, - KratosMultiphysics.DISPLACEMENT) - - self.neg_interface_mapper.InverseMap(KratosMultiphysics.VECTOR_PROJECTED, - KratosMultiphysics.DISPLACEMENT) - - #TODO: One of these mappings is not needed. At the moment both are performed to ensure that - # the _GetFluidInterfaceSubmodelPart(), which is the one used to compute the interface residual, - # gets the structure DISPLACEMENT. Think a way to properly identify the reference fluid interface. - disp_residual = self.partitioned_fsi_utilities.SetUpInterfaceVector(self._GetFluidInterfaceSubmodelPart()) - self.partitioned_fsi_utilities.ComputeInterfaceResidualVector( - self._GetFluidInterfaceSubmodelPart(), - KratosMultiphysics.MESH_DISPLACEMENT, - KratosMultiphysics.VECTOR_PROJECTED, - KratosMultiphysics.FSI_INTERFACE_RESIDUAL, - disp_residual, - "nodal", - KratosMultiphysics.FSI_INTERFACE_RESIDUAL_NORM) - - return disp_residual \ No newline at end of file diff --git a/applications/FSIApplication/tests/FSI_problem_emulator_test.py b/applications/FSIApplication/tests/FSI_problem_emulator_test.py index dbbecee87ca8..d6bc72da3206 100644 --- a/applications/FSIApplication/tests/FSI_problem_emulator_test.py +++ b/applications/FSIApplication/tests/FSI_problem_emulator_test.py @@ -1,5 +1,6 @@ from KratosMultiphysics import * from KratosMultiphysics.FSIApplication import * +import KratosMultiphysics.StructuralMechanicsApplication as KratosStructural import KratosMultiphysics.KratosUnittest as UnitTest import KratosMultiphysics.kratos_utilities as KratosUtils @@ -21,7 +22,7 @@ def __enter__(self): def __exit__(self, type, value, traceback): os.chdir(self.currentPath) -@UnitTest.skipIfApplicationsNotAvailable("StructuralMechanicsApplication, LinearSolversApplication") +@UnitTest.skipIfApplicationsNotAvailable("StructuralMechanicsApplication", "LinearSolversApplication") class FSIProblemEmulatorTest(UnitTest.TestCase): def setUp(self): @@ -48,16 +49,27 @@ def deleteOutFile(self,filename): except FileNotFoundError as e: pass - def testFSIProblemEmulatorWithAitken(self): + def test_FSI_problem_emulator_with_aitken(self): self.coupling_utility = AitkenConvergenceAccelerator(self.initial_relaxation) self.RunTestCase() - def testFSIProblemEmulatorWithMVQN(self): + def test_FSI_problem_emulator_with_MVQN(self): abs_cut_off = 1.0e-2 - self.coupling_utility = MVQNFullJacobianConvergenceAccelerator(self.initial_relaxation, abs_cut_off) + used_in_block_newton = False + self.coupling_utility = MVQNFullJacobianConvergenceAccelerator(self.initial_relaxation, abs_cut_off, used_in_block_newton) self.RunTestCase() - def testFSIProblemEmulatorWithMVQNRecursive(self): + def test_FSI_problem_emulator_with_IBQN_MVQN(self): + abs_cut_off = 1.0e-2 + self.fluid_emulator_stiffness = 1000.0 + ibqn_mvqn_settings = Parameters(r'''{ + "w_0" : 0.825, + "abs_cut_off_tol" : 1e-2 + }''') + self.coupling_utility = IBQNMVQNConvergenceAccelerator(ibqn_mvqn_settings) + self.RunTestCaseIBN() + + def test_FSI_problem_emulator_with_MVQN_recursive(self): buffer_size = 7 abs_cut_off = 1.0e-2 self.coupling_utility = MVQNRecursiveJacobianConvergenceAccelerator(self.initial_relaxation, buffer_size, abs_cut_off) @@ -178,6 +190,144 @@ def RunTestCase(self): # Unitcest convergence criterion check self.assertLess(nl_res_norm, self.nl_tol) + def RunTestCaseIBN(self): + StructureSolverSettings = Parameters(""" + { + "problem_data": { + "parallel_type" : "OpenMP" + }, + "solver_settings" : { + "model_part_name" : "Structure", + "domain_size" : 2, + "solver_type" : "Dynamic", + "echo_level" : 0, + "analysis_type" : "linear", + "time_integration_method" : "implicit", + "scheme_type" : "bossak", + "model_import_settings" : { + "input_type" : "mdpa", + "input_filename" : "test_FSI_emulator_Structural", + "input_file_label" : 0 + }, + "material_import_settings" :{ + "materials_filename": "materials_2D.json" + }, + "line_search" : false, + "convergence_criterion" : "Residual_criterion", + "displacement_relative_tolerance" : 1e-8, + "displacement_absolute_tolerance" : 1e-10, + "residual_relative_tolerance" : 1e-8, + "residual_absolute_tolerance" : 1e-10, + "max_iteration" : 20, + "rotation_dofs" : false, + "linear_solver_settings" : { + "solver_type" : "LinearSolversApplication.sparse_lu", + "scaling" : true + } + } + } + """) + + with WorkFolderScope(self.work_folder): + + self.model = Model() + + # Construct the structure solver + self.structure_solver = python_solvers_wrapper_structural.CreateSolver(self.model, StructureSolverSettings) + + self.structure_solver.AddVariables() + + self.structure_solver.ImportModelPart() + + self.structure_solver.PrepareModelPart() + + self.structure_main_model_part = self.model["Structure"] + + self.structure_solver.AddDofs() + + self.SetStructureBoundaryConditions() + + self.structure_solver.Initialize() + + self.coupling_utility.Initialize() + + residual_size = self.GetInterfaceProblemSize()*2 # Interface DOFs number times PROBLEM_SIZE + self.iteration_value_u = Vector(residual_size) # Interface displacement iteration guess + self.iteration_value_f = Vector(residual_size) # Interface fluxes iteration guess + self.corrected_iteration_value_u = Vector(residual_size) # Interface displacement iteration guess + self.corrected_iteration_value_f = Vector(residual_size) # Interface fluxes iteration guess + for i in range(0,residual_size): + self.iteration_value_u[i] = 0.0 + self.iteration_value_f[i] = 0.0 + self.corrected_iteration_value_u[i] = 0.0 + self.corrected_iteration_value_f[i] = 0.0 + + step = 0 + time = 0.0 + + while(time <= self.end_time): + + time = time + self.Dt + step = step + 1 + + print("##################################") + print("########## step = ", step, "#############") + print("##################################") + + self.structure_solver.main_model_part.ProcessInfo.SetValue(TIME_STEPS, step) + + self.structure_main_model_part.CloneTimeStep(time) + + self.PointLoadUpdate() + + self.structure_solver.InitializeSolutionStep() + self.structure_solver.Predict() + + self.coupling_utility.InitializeSolutionStep() + + # Compute and check first residual + disp_residual = self.__ComputeInitialResidual() + nl_res_norm = UblasSparseSpace().TwoNorm(disp_residual) + if nl_res_norm > self.nl_tol: + for nl_it in range(self.max_nl_it): + + self.coupling_utility.InitializeNonLinearIteration() + + # Update the structure displacement values + self.coupling_utility.UpdateSolutionRight(self.corrected_iteration_value_f, self.iteration_value_u, self.corrected_iteration_value_u) + + # Solve fluid emulator with the obtained displacements + self.__SolveFluidEmulator() + + # Update the fluid emulator force values + self.coupling_utility.UpdateSolutionLeft(self.corrected_iteration_value_u, self.iteration_value_f, self.corrected_iteration_value_f) + + # Finalize the current non-linear iteration + self.coupling_utility.FinalizeNonLinearIteration() + + # Transfer fluid emulator load to structure + self.__TransferFluidEmulatorLoad() + + # Solve the structure problem + self.structure_solver.SolveSolutionStep() + + # Compute displalcement residual + disp_residual = self.__ComputeStructureResidual() + + # Residual computation + nl_res_norm = UblasSparseSpace().TwoNorm(disp_residual) + print("nl_it: ",nl_it," nl_res_norm: ",nl_res_norm) + + # Check convergence + if nl_res_norm < self.nl_tol: + break + + self.structure_solver.FinalizeSolutionStep() + self.coupling_utility.FinalizeSolutionStep() + + # Unitcest convergence criterion check + self.assertLess(nl_res_norm, self.nl_tol) + def SetStructureBoundaryConditions(self): zero_vect = Vector(3) zero_vect[0] = 0.0 @@ -193,7 +343,7 @@ def SetStructureBoundaryConditions(self): # Set initial point load value for node in self.structure_main_model_part.GetSubModelPart("PointLoad2D_Point_load").Nodes: - node.SetSolutionStepValue(POINT_LOAD_X, 0, self.initial_point_load) + node.SetSolutionStepValue(KratosStructural.POINT_LOAD_X, 0, self.initial_point_load) # Set the structure interface for node in self.structure_main_model_part.GetSubModelPart("StructureInterface2D_Solid_interface").Nodes: @@ -215,8 +365,8 @@ def SetStructureBoundaryConditions(self): def PointLoadUpdate(self): for node in self.structure_main_model_part.GetSubModelPart("PointLoad2D_Point_load").Nodes: - point_load = node.GetSolutionStepValue(POINT_LOAD_X) - node.SetSolutionStepValue(POINT_LOAD_X, 0, self.point_load_updater*point_load) + point_load = node.GetSolutionStepValue(KratosStructural.POINT_LOAD_X) + node.SetSolutionStepValue(KratosStructural.POINT_LOAD_X, 0, self.point_load_updater*point_load) def GetInterfaceProblemSize(self): return len(self.structure_solver.main_model_part.GetSubModelPart("StructureInterface2D_Solid_interface").Nodes) @@ -235,7 +385,7 @@ def ComputeDirichletNeumannResidual(self): point_load[1] = - K*self.iteration_value[i+1] point_load[2] = 0.0 - node.SetSolutionStepValue(POINT_LOAD, 0, point_load) + node.SetSolutionStepValue(KratosStructural.POINT_LOAD, 0, point_load) i += 2 @@ -255,10 +405,63 @@ def ComputeDirichletNeumannResidual(self): return disp_residual + def __ComputeInitialResidual(self): + # Solve the fluid emulator problem with the initial displacement guess + self.__SolveFluidEmulator() + + # Transfer fluid load + for i in range(len(self.corrected_iteration_value_f)): + self.corrected_iteration_value_f[i] = self.iteration_value_f[i] + self.__TransferFluidEmulatorLoad() + + # Solve structure problem + self.structure_solver.SolveSolutionStep() + + # Compute the displacement residual + disp_residual = self.__ComputeStructureResidual() + + return disp_residual + + def __SolveFluidEmulator(self): + # Calculate the spring reactions that emulate the fluid load over the structure interface + for i in range(self.GetInterfaceProblemSize()): + self.iteration_value_f[2*i] = self.fluid_emulator_stiffness * self.corrected_iteration_value_u[2*i] + self.iteration_value_f[2*i+1] = self.fluid_emulator_stiffness * self.corrected_iteration_value_u[2*i+1] + + def __TransferFluidEmulatorLoad(self): + interface_submodelpart = self.structure_solver.main_model_part.GetSubModelPart("StructureInterface2D_Solid_interface") + + i = 0 + for node in interface_submodelpart.Nodes: + point_load = Vector(3) + point_load[0] = - self.corrected_iteration_value_f[i] + point_load[1] = - self.corrected_iteration_value_f[i+1] + point_load[2] = 0.0 + node.SetSolutionStepValue(KratosStructural.POINT_LOAD, 0, point_load) + i += 2 + + def __ComputeStructureResidual(self): + interface_submodelpart = self.structure_solver.main_model_part.GetSubModelPart("StructureInterface2D_Solid_interface") + + # Calculate the structure displacement error + disp_residual = Vector(2 * self.GetInterfaceProblemSize()) + + i = 0 + for node in interface_submodelpart.Nodes: + disp = node.GetSolutionStepValue(DISPLACEMENT,0) + self.iteration_value_u[i] = disp[0] + self.iteration_value_u[i+1] = disp[1] + disp_residual[i] = disp[0] - self.corrected_iteration_value_u[i] + disp_residual[i+1] = disp[1] - self.corrected_iteration_value_u[i+1] + i+=2 + + return disp_residual + if __name__ == '__main__': test = FSIProblemEmulatorTest() test.setUp() - # test.testFSIProblemEmulatorWithAitken() - # test.testFSIProblemEmulatorWithMVQN() - test.testFSIProblemEmulatorWithMVQNRecursive() + # test.test_FSI_problem_emulator_with_aitken() + # test.test_FSI_problem_emulator_with_MVQN() + test.test_FSI_problem_emulator_with_IBQN_MVQN() + # test.test_FSI_problem_emulator_with_MVQN_recursive() test.tearDown() diff --git a/applications/FSIApplication/tests/convergence_accelerator_spring_test.py b/applications/FSIApplication/tests/convergence_accelerator_spring_test.py index 3bb5077304da..3ce2656abe55 100644 --- a/applications/FSIApplication/tests/convergence_accelerator_spring_test.py +++ b/applications/FSIApplication/tests/convergence_accelerator_spring_test.py @@ -128,7 +128,7 @@ def tearDown(self): for f in glob.glob(GetFilePath('*.time')): os.remove(f) - def test_accelerator(self,force1,force2,solution,accelerator_settings): + def _test_accelerator(self,force1,force2,solution,accelerator_settings): print("") print("Testing accelerator: ",accelerator_settings["solver_type"].GetString()) @@ -170,7 +170,7 @@ def test_accelerator(self,force1,force2,solution,accelerator_settings): self.assertAlmostEqual(expected_x[i],x_guess[i],delta=self.assert_delta) # MVQN recursive accelerator test - def test_mvqn_recursive_accelerator(self,force1,force2,solution): + def _test_mvqn_recursive_accelerator(self,force1,force2,solution): mvqn_recursive_settings = KratosMultiphysics.Parameters(""" { @@ -179,7 +179,7 @@ def test_mvqn_recursive_accelerator(self,force1,force2,solution): "buffer_size": 5 }""") - self.test_accelerator(force1,force2,solution,mvqn_recursive_settings) + self._test_accelerator(force1,force2,solution,mvqn_recursive_settings) def test_mvqn_recursive_accelerator_constant_forces(self): @@ -209,7 +209,7 @@ def analytical_solution(model_part,k1,k2,z_equilibrium_1,z_equilibrium_2): def solution(model_part): return analytical_solution(model_part,k1,k2,z_equilibrium_1,z_equilibrium_2) - self.test_mvqn_recursive_accelerator(force1,force2,solution) + self._test_mvqn_recursive_accelerator(force1,force2,solution) def test_mvqn_recursive_accelerator_variable_stiffness(self): @@ -240,10 +240,10 @@ def analytical_solution(model_part,k1,k2,z_equilibrium_1,z_equilibrium_2): def solution(model_part): return analytical_solution(model_part,k1,k2,z_equilibrium_1,z_equilibrium_2) - self.test_mvqn_recursive_accelerator(forceA,forceB,solution) + self._test_mvqn_recursive_accelerator(forceA,forceB,solution) # Aitken accelerator test - def test_aitken_accelerator(self,force1,force2,solution): + def _test_aitken_accelerator(self,force1,force2,solution): aitken_settings = KratosMultiphysics.Parameters("""{ "solver_type" : "Relaxation", @@ -251,7 +251,7 @@ def test_aitken_accelerator(self,force1,force2,solution): "w_0" : 0.825 }""") - self.test_accelerator(force1,force2,solution,aitken_settings) + self._test_accelerator(force1,force2,solution,aitken_settings) def test_aitken_accelerator_constant_forces(self): @@ -281,7 +281,7 @@ def analytical_solution(model_part,k1,k2,z_equilibrium_1,z_equilibrium_2): def solution(model_part): return analytical_solution(model_part,k1,k2,z_equilibrium_1,z_equilibrium_2) - self.test_aitken_accelerator(force1,force2,solution) + self._test_aitken_accelerator(force1,force2,solution) def test_aitken_accelerator_variable_stiffness(self): @@ -312,7 +312,7 @@ def analytical_solution(model_part,k1,k2,z_equilibrium_1,z_equilibrium_2): def solution(model_part): return analytical_solution(model_part,k1,k2,z_equilibrium_1,z_equilibrium_2) - self.test_aitken_accelerator(forceA,forceB,solution) + self._test_aitken_accelerator(forceA,forceB,solution) if __name__ == '__main__': test = ConvergenceAcceleratorSpringTest() diff --git a/applications/FSIApplication/tests/cpp_tests/test_partitioned_fsi_utilities.cpp b/applications/FSIApplication/tests/cpp_tests/test_partitioned_fsi_utilities.cpp index b9bcbd46d92f..1dad2f7b6885 100644 --- a/applications/FSIApplication/tests/cpp_tests/test_partitioned_fsi_utilities.cpp +++ b/applications/FSIApplication/tests/cpp_tests/test_partitioned_fsi_utilities.cpp @@ -212,7 +212,7 @@ namespace Testing { // Check results double tol = 1.0e-10; unsigned int aux_count = 0; - std::array expected_values = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; + std::array expected_values = {-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0}; for (auto &r_node : main_model_part.Nodes()) { const auto &r_fsi_int_res = r_node.FastGetSolutionStepValue(FSI_INTERFACE_RESIDUAL); for (unsigned int i = 0; i < 3; ++i) { @@ -222,7 +222,7 @@ namespace Testing { } } - KRATOS_TEST_CASE_IN_SUITE(PartitionedFSIUtilitiesCopySkinToElements, FSIApplicationFastSuite) + KRATOS_TEST_CASE_IN_SUITE(PartitionedFSIUtilitiesCreateCouplingSkin, FSIApplicationFastSuite) { // Set the partitioned FSI utilities PartitionedFSIUtilities,2> partitioned_fsi_utilities; @@ -233,13 +233,13 @@ namespace Testing { GenerateTestSkinModelPart(main_model_part); // Set the new skin model part - ModelPart &element_based_skin = model.CreateModelPart("ElementBasedSkin"); - partitioned_fsi_utilities.CreateCouplingElementBasedSkin(main_model_part, element_based_skin); + ModelPart &element_based_skin = model.CreateModelPart("ConditionBasedSkin"); + partitioned_fsi_utilities.CreateCouplingSkin(main_model_part, element_based_skin); // Check results KRATOS_CHECK_EQUAL(element_based_skin.NumberOfNodes(), 4); - KRATOS_CHECK_EQUAL(element_based_skin.NumberOfElements(), 3); - KRATOS_CHECK_EQUAL(element_based_skin.NumberOfConditions(), 0); + KRATOS_CHECK_EQUAL(element_based_skin.NumberOfElements(), 0); + KRATOS_CHECK_EQUAL(element_based_skin.NumberOfConditions(), 3); } KRATOS_TEST_CASE_IN_SUITE(PartitionedFSIUtilitiesDoubleGetInterfaceResidualsize, FSIApplicationFastSuite) @@ -339,10 +339,8 @@ namespace Testing { *p_interface_vector); const double tolerance = 1.0e-8; - std::vector expected_values = {-1.0, -1.0, -1.0, -1.0}; - for (unsigned int i = 0; i < expected_values.size(); ++i) { - KRATOS_CHECK_NEAR(expected_values[i], (*p_interface_vector)[i], tolerance); - } + std::vector expected_values = {1.0,1.0,1.0,1.0}; + KRATOS_CHECK_VECTOR_NEAR(expected_values, (*p_interface_vector), tolerance) } KRATOS_TEST_CASE_IN_SUITE(PartitionedFSIUtilitiesArray2DComputeInterfaceResidualVectorNodal, FSIApplicationFastSuite) @@ -365,10 +363,8 @@ namespace Testing { *p_interface_vector); const double tolerance = 1.0e-8; - std::vector expected_values = {0.0,0.0,-1.0,-1.0,-2.0,-2.0,-3.0,-3.0}; - for (unsigned int i = 0; i < expected_values.size(); ++i) { - KRATOS_CHECK_NEAR(expected_values[i], (*p_interface_vector)[i], tolerance); - } + std::vector expected_values = {0.0,0.0,1.0,1.0,2.0,2.0,3.0,3.0}; + KRATOS_CHECK_VECTOR_NEAR(expected_values, (*p_interface_vector), tolerance) } KRATOS_TEST_CASE_IN_SUITE(PartitionedFSIUtilitiesArray2DComputeInterfaceResidualVectorConsistent, FSIApplicationFastSuite) @@ -399,29 +395,6 @@ namespace Testing { } } - KRATOS_TEST_CASE_IN_SUITE(PartitionedFSIUtilitiesArray2DCreateCouplingElementBasedSkin, FSIApplicationFastSuite) - { - // Set the partitioned FSI utilities - PartitionedFSIUtilities,2> partitioned_fsi_utilities; - - // Set the model part containing the origin skin - Model model; - ModelPart &r_skin_model_part = model.CreateModelPart("OriginModelPart"); - GenerateTestSkinModelPart(r_skin_model_part); - - // Create the destination submodelpart - ModelPart &r_destination_model_part = model.CreateModelPart("DestinationModelPart"); - - // Generate the auxiliary element based skin - partitioned_fsi_utilities.CreateCouplingElementBasedSkin( - r_skin_model_part, - r_destination_model_part); - - // Check results - KRATOS_CHECK_EQUAL(r_destination_model_part.NumberOfNodes(), 4); - KRATOS_CHECK_EQUAL(r_destination_model_part.NumberOfElements(), 3); - } - KRATOS_TEST_CASE_IN_SUITE(PartitionedFSIUtilitiesArray2DInitializeInterfaceVector, FSIApplicationFastSuite) { // Set the partitioned FSI utilities @@ -451,10 +424,8 @@ namespace Testing { // Check results const double tolerance = 1.0e-8; - std::array expected_results = {1.0,2.0,2.0,4.0,3.0,6.0,4.0,8.0}; - for (unsigned int i = 0; i < 8; ++i) { - KRATOS_CHECK_NEAR(interface_vector(i), expected_results[i], tolerance); - } + std::vector expected_results = {1.0,2.0,2.0,4.0,3.0,6.0,4.0,8.0}; + KRATOS_CHECK_VECTOR_NEAR(expected_results, interface_vector, tolerance) } KRATOS_TEST_CASE_IN_SUITE(PartitionedFSIUtilitiesArray2DEmbeddedToPositiveFacePressureInterpolator, FSIApplicationFastSuite) @@ -483,7 +454,8 @@ namespace Testing { Parameters mesher_parameters(R"( { "number_of_divisions": 7, - "element_name": "Element2D3N" + "element_name": "Element2D3N", + "create_skin_sub_model_part": false })"); StructuredMeshGeneratorProcess(geometry, r_background_model_part, mesher_parameters).Execute(); @@ -497,11 +469,6 @@ namespace Testing { r_background_model_part, r_skin_model_part); - // Copy the obtained values from PRESSURE to POSITIVE_FACE_PRESSURE - for (auto &r_node : r_skin_model_part.Nodes()) { - r_node.FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE) = r_node.FastGetSolutionStepValue(PRESSURE); - } - // Check results unsigned int i = 0; const double tolerance = 1.0e-4; diff --git a/applications/FSIApplication/tests/fsi_coupling_interface_test.py b/applications/FSIApplication/tests/fsi_coupling_interface_test.py index 8f64c8651705..6f0ec7b3aa2f 100644 --- a/applications/FSIApplication/tests/fsi_coupling_interface_test.py +++ b/applications/FSIApplication/tests/fsi_coupling_interface_test.py @@ -67,7 +67,8 @@ def runTest(self): node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT, [0.01 * node.Id, 0.0, 0.0]) # Perform the update - residual = self.fsi_coupling_interface.Update() + self.fsi_coupling_interface.ComputeResidualVector() + self.fsi_coupling_interface.Update() def tearDown(self): with UnitTest.WorkFolderScope(self.work_folder, __file__): diff --git a/applications/FSIApplication/tests/test_FSIApplication.py b/applications/FSIApplication/tests/test_FSIApplication.py index ecf08d58cf16..b721afd6c434 100644 --- a/applications/FSIApplication/tests/test_FSIApplication.py +++ b/applications/FSIApplication/tests/test_FSIApplication.py @@ -34,18 +34,10 @@ def AssembleTestSuites(): # Create a test suit with the selected tests (Small tests): smallSuite = suites['small'] - smallSuite.addTest(ConvergenceAcceleratorTest('test_aitken_accelerator')) - smallSuite.addTest(ConvergenceAcceleratorTest('test_mvqn_accelerator')) - smallSuite.addTest(ConvergenceAcceleratorTest('test_mvqn_recusive_accelerator')) - smallSuite.addTest(ConvergenceAcceleratorTest('test_accelerator_with_jacobian')) - smallSuite.addTest(FSICouplingInterfaceTest('test_fsi_coupling_interface')) - smallSuite.addTest(FSIProblemEmulatorTest('testFSIProblemEmulatorWithAitken')) - smallSuite.addTest(FSIProblemEmulatorTest('testFSIProblemEmulatorWithMVQN')) - smallSuite.addTest(FSIProblemEmulatorTest('testFSIProblemEmulatorWithMVQNRecursive')) - smallSuite.addTest(ConvergenceAcceleratorSpringTest('test_aitken_accelerator_constant_forces')) - smallSuite.addTest(ConvergenceAcceleratorSpringTest('test_aitken_accelerator_variable_stiffness')) - smallSuite.addTest(ConvergenceAcceleratorSpringTest('test_mvqn_recursive_accelerator_constant_forces')) - smallSuite.addTest(ConvergenceAcceleratorSpringTest('test_mvqn_recursive_accelerator_variable_stiffness')) + smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([ConvergenceAcceleratorTest])) + smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([FSICouplingInterfaceTest])) + smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([FSIProblemEmulatorTest])) + smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([ConvergenceAcceleratorSpringTest])) smallSuite.addTest(NonConformantOneSideMapTest('test2D_1')) smallSuite.addTest(NonConformantOneSideMapTest('test2D_2')) smallSuite.addTest(NonConformantOneSideMapTest('test3D_1')) diff --git a/applications/FemToDemApplication/CMakeLists.txt b/applications/FemToDemApplication/CMakeLists.txt index c1e2fc74d57f..722f1ab1b16b 100644 --- a/applications/FemToDemApplication/CMakeLists.txt +++ b/applications/FemToDemApplication/CMakeLists.txt @@ -71,6 +71,11 @@ pybind11_add_module(KratosFemToDemApplication MODULE ${KRATOS_FEM_TO_DEM_APPLICA target_link_libraries(KratosFemToDemApplication PRIVATE KratosStructuralMechanicsCore KratosDEMCore KratosMeshingCore KratosCore KratosPfemFluidDynamicsCore) set_target_properties(KratosFemToDemApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosFemToDemApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosFemToDemApplication PROPERTIES SUFFIX .pyd) @@ -81,11 +86,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosFemToDemApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosFemToDemApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/FemToDemApplication.py KratosMultiphysics/FemToDemApplication/__init__.py ) diff --git a/applications/FemToDemApplication/custom_problemtype/FemDemKratos.gid/MdpaDEM.tcl b/applications/FemToDemApplication/custom_problemtype/FemDemKratos.gid/MdpaDEM.tcl index 453afb345b4d..615261d0acb7 100644 --- a/applications/FemToDemApplication/custom_problemtype/FemDemKratos.gid/MdpaDEM.tcl +++ b/applications/FemToDemApplication/custom_problemtype/FemDemKratos.gid/MdpaDEM.tcl @@ -12,8 +12,8 @@ proc WriteMdpaDEM { basename dir problemtypedir } { puts $FileVar " PARTICLE_DENSITY [GiD_AccessValue get gendata Density]" puts $FileVar " YOUNG_MODULUS [GiD_AccessValue get gendata Young_Modulus]" puts $FileVar " POISSON_RATIO [GiD_AccessValue get gendata Poisson_Ratio]" - puts $FileVar " DYNAMIC_FRICTION [GiD_AccessValue get gendata Particle_Friction]" - puts $FileVar " STATIC_FRICTION [GiD_AccessValue get gendata Particle_Friction]" + puts $FileVar " STATIC_FRICTION [GiD_AccessValue get gendata Static_Friction]" + puts $FileVar " DYNAMIC_FRICTION [GiD_AccessValue get gendata Dynamic_Friction]" puts $FileVar " PARTICLE_COHESION [GiD_AccessValue get gendata Cohesion]" puts $FileVar " COEFFICIENT_OF_RESTITUTION [GiD_AccessValue get gendata Coefficion_of_Restitution]" puts $FileVar " PARTICLE_MATERIAL [GiD_AccessValue get gendata Color]" @@ -24,19 +24,19 @@ proc WriteMdpaDEM { basename dir problemtypedir } { puts $FileVar "" close $FileVar - # create empty mdpa + # create empty mdpa # set basenameCluster $basename # append basenameCluster "DEM_Clusters" # set filename [file join $dir ${basenameCluster}.mdpa] # set FileVar [open $filename w] # close $FileVar - + # set basenameDEMFEM $basename # append basenameDEMFEM "DEM_FEM_boundary" # set filename [file join $dir ${basenameDEMFEM}.mdpa] # set FileVar [open $filename w] # close $FileVar - + # set basenameDEMinlet $basename # append basenameDEMinlet "DEM_Inlet" # set filename [file join $dir ${basenameDEMinlet}.mdpa] diff --git a/applications/FemToDemApplication/custom_problemtype/FemDemKratos3D.gid/MdpaDEM.tcl b/applications/FemToDemApplication/custom_problemtype/FemDemKratos3D.gid/MdpaDEM.tcl index 453afb345b4d..615261d0acb7 100644 --- a/applications/FemToDemApplication/custom_problemtype/FemDemKratos3D.gid/MdpaDEM.tcl +++ b/applications/FemToDemApplication/custom_problemtype/FemDemKratos3D.gid/MdpaDEM.tcl @@ -12,8 +12,8 @@ proc WriteMdpaDEM { basename dir problemtypedir } { puts $FileVar " PARTICLE_DENSITY [GiD_AccessValue get gendata Density]" puts $FileVar " YOUNG_MODULUS [GiD_AccessValue get gendata Young_Modulus]" puts $FileVar " POISSON_RATIO [GiD_AccessValue get gendata Poisson_Ratio]" - puts $FileVar " DYNAMIC_FRICTION [GiD_AccessValue get gendata Particle_Friction]" - puts $FileVar " STATIC_FRICTION [GiD_AccessValue get gendata Particle_Friction]" + puts $FileVar " STATIC_FRICTION [GiD_AccessValue get gendata Static_Friction]" + puts $FileVar " DYNAMIC_FRICTION [GiD_AccessValue get gendata Dynamic_Friction]" puts $FileVar " PARTICLE_COHESION [GiD_AccessValue get gendata Cohesion]" puts $FileVar " COEFFICIENT_OF_RESTITUTION [GiD_AccessValue get gendata Coefficion_of_Restitution]" puts $FileVar " PARTICLE_MATERIAL [GiD_AccessValue get gendata Color]" @@ -24,19 +24,19 @@ proc WriteMdpaDEM { basename dir problemtypedir } { puts $FileVar "" close $FileVar - # create empty mdpa + # create empty mdpa # set basenameCluster $basename # append basenameCluster "DEM_Clusters" # set filename [file join $dir ${basenameCluster}.mdpa] # set FileVar [open $filename w] # close $FileVar - + # set basenameDEMFEM $basename # append basenameDEMFEM "DEM_FEM_boundary" # set filename [file join $dir ${basenameDEMFEM}.mdpa] # set FileVar [open $filename w] # close $FileVar - + # set basenameDEMinlet $basename # append basenameDEMinlet "DEM_Inlet" # set filename [file join $dir ${basenameDEMinlet}.mdpa] diff --git a/applications/FemToDemApplication/python_scripts/DEMmain_script.py b/applications/FemToDemApplication/python_scripts/DEMmain_script.py index 15ff059a5735..a238873fd089 100644 --- a/applications/FemToDemApplication/python_scripts/DEMmain_script.py +++ b/applications/FemToDemApplication/python_scripts/DEMmain_script.py @@ -69,7 +69,7 @@ def __init__(self, model, path = ""): self.SetAnalyticParticleWatcher() self.PreUtilities = PreUtilities() self.aux = AuxiliaryUtilities() - + # Set the print function TO_DO: do this better... @@ -138,18 +138,12 @@ def SetAnalyticParticleWatcher(self): def SetAnalyticFaceWatcher(self): from KratosMultiphysics.DEMApplication.analytic_tools import analytic_data_procedures - self.FaceAnalyzerClass = analytic_data_procedures.FaceWatcherAnalyzer - self.face_watcher_dict = dict() - self.face_watcher_analysers = dict() - for sub_part in self.rigid_face_model_part.SubModelParts: - if sub_part[IS_GHOST] == True: - name = sub_part.Name - self.face_watcher_dict[sub_part.Name] = AnalyticFaceWatcher(sub_part) - self.face_watcher_analysers[sub_part.Name] = analytic_data_procedures.FaceWatcherAnalyzer(name=name, analytic_face_watcher=self.face_watcher_dict[sub_part.Name], path=self.main_path) + self.FaceAnalyzerClass = analytic_data_procedures.FaceAnalyzerClass(self.rigid_face_model_part.SubModelParts, self.main_path) def MakeAnalyticsMeasurements(self): - for face_watcher in self.face_watcher_dict.values(): - face_watcher.MakeMeasurements() + pass + # for face_watcher in self.face_watcher_dict.values(): + # face_watcher.MakeMeasurements() def SetFinalTime(self): self.end_time = self.DEM_parameters["FinalTime"].GetDouble() @@ -472,13 +466,10 @@ def RunMainTemporalLoop(self): break def RunAnalytics(self, time, is_time_to_print=True): - for sp in (sp for sp in self.rigid_face_model_part.SubModelParts if sp[IS_GHOST]): - self.MakeAnalyticsMeasurements() - if is_time_to_print: - self.FaceAnalyzerClass.CreateNewFile() - for sp in (sp for sp in self.rigid_face_model_part.SubModelParts if sp[IS_GHOST]): - self.face_watcher_analysers[sp.Name].UpdateDataFiles(time) - self.FaceAnalyzerClass.RemoveOldFile() + pass + # self.MakeAnalyticsMeasurements() + # if is_time_to_print: + # self.FaceAnalyzerClass.MakeAnalyticsPipeLine(time) def IsTimeToPrintPostProcess(self): return self.DEM_parameters["OutputTimeStep"].GetDouble() - (self.time - self.time_old_print) < 1e-2 * self.solver.dt @@ -489,12 +480,9 @@ def PrintResults(self): self.PrintResultsForGid(self.time) self.time_old_print = self.time - def UpdateTimeInModelParts(self): - self.DEMFEMProcedures.UpdateTimeInModelParts(self.all_model_parts, self.time, self.solver.dt, self.step, self.IsTimeToPrintPostProcess()) + self.solver._UpdateTimeInModelParts(self.time, self.IsTimeToPrintPostProcess()) - def UpdateTimeInOneModelPart(self): - pass def SolverSolve(self): self.solver.SolveSolutionStep() @@ -644,7 +632,7 @@ def InitializeTime(self): def _UpdateTimeParameters(self): self.time = self.time + self.solver.dt self.step += 1 - self.DEMFEMProcedures.UpdateTimeInModelParts(self.all_model_parts, self.time, self.solver.dt, self.step) + self.solver.UpdateTimeInModelParts(self.time, self.IsTimeToPrintPostProcess()) def FinalizeSingleTimeStep(self): self.solver._MoveAllMeshes(self.time, self.solver.dt) diff --git a/applications/FemToDemApplication/python_scripts/MainCouplingFemDem.py b/applications/FemToDemApplication/python_scripts/MainCouplingFemDem.py index b703b4d17c45..0835ecd00b57 100644 --- a/applications/FemToDemApplication/python_scripts/MainCouplingFemDem.py +++ b/applications/FemToDemApplication/python_scripts/MainCouplingFemDem.py @@ -929,11 +929,7 @@ def ExecuteAfterGeneratingDEM(self): def BeforeSolveDEMOperations(self): self.DEM_Solution.time = self.FEM_Solution.time self.DEM_Solution.step = self.FEM_Solution.step - self.DEM_Solution.DEMFEMProcedures.UpdateTimeInModelParts(self.DEM_Solution.all_model_parts, - self.DEM_Solution.time, - self.DEM_Solution.solver.dt, - self.DEM_Solution.step, - self.DEM_Solution.IsTimeToPrintPostProcess()) + self.DEM_Solution.UpdateTimeInModelParts() #TransferFEMSkinToDEM============================================================================================================================ def TransferFEMSkinToDEM(self): @@ -969,6 +965,7 @@ def CreateFEMPropertiesForDEFEContact(self): self.created_props_id = max_id_properties + 1 props[KratosDEM.STATIC_FRICTION] = -0.5773502691896257 props[KratosDEM.DYNAMIC_FRICTION] = -0.5773502691896257 + props[KratosDEM.FRICTION_DECAY] = 500 props[KratosDEM.WALL_COHESION] = 0.0 props[KratosDEM.COMPUTE_WEAR] = False props[KratosDEM.SEVERITY_OF_WEAR] = 0.001 diff --git a/applications/FemToDemApplication/python_scripts/MainCouplingFemDemSubstepping.py b/applications/FemToDemApplication/python_scripts/MainCouplingFemDemSubstepping.py index 95dffeed3785..2d2ff39b82b6 100644 --- a/applications/FemToDemApplication/python_scripts/MainCouplingFemDemSubstepping.py +++ b/applications/FemToDemApplication/python_scripts/MainCouplingFemDemSubstepping.py @@ -109,11 +109,7 @@ def FinalizeSolutionStep(self): def BeforeSolveDEMOperations(self): self.DEM_Solution.time += self.DEM_Solution.solver.dt self.DEM_Solution.step += 1 - self.DEM_Solution.DEMFEMProcedures.UpdateTimeInModelParts(self.DEM_Solution.all_model_parts, - self.DEM_Solution.time, - self.DEM_Solution.solver.dt, - self.DEM_Solution.step, - self.DEM_Solution.IsTimeToPrintPostProcess()) + self.DEM_Solution.UpdateTimeInModelParts() #============================================================================================================================ def OnlyUpdateTimeAndStepInDEM(self): diff --git a/applications/FemToDemApplication/python_scripts/MainFEM_for_PFEM_coupling.py b/applications/FemToDemApplication/python_scripts/MainFEM_for_PFEM_coupling.py index e5f9fdbf46b1..02ab16ab0f41 100644 --- a/applications/FemToDemApplication/python_scripts/MainFEM_for_PFEM_coupling.py +++ b/applications/FemToDemApplication/python_scripts/MainFEM_for_PFEM_coupling.py @@ -12,13 +12,13 @@ class FEM_for_PFEM_coupling_Solution(MainFEM_for_coupling.FEM_for_coupling_Solution): def Info(self): - print("FEM part of the FEMDEM application") + print("FEM part of the FEMDEM application") def Initialize(self): #### INITIALIZE #### - + # Add variables (always before importing the model part) self.solver.AddVariables() @@ -91,7 +91,7 @@ def Initialize(self): self.main_model_part.AddNodalSolutionStepVariable(KratosFemDem.ACCELERATION_BACKUP) self.main_model_part.AddNodalSolutionStepVariable(KratosFemDem.DISPLACEMENT_BACKUP) - + # Read model_part (note: the buffer_size is set here) (restart is read here) self.solver.ImportModelPart() @@ -104,7 +104,7 @@ def Initialize(self): # Add materials (assign material to model_parts if Materials.json exists) self.AddMaterials() - + # Add processes self.model_processes = self.AddProcesses() self.model_processes.ExecuteInitialize() @@ -126,7 +126,7 @@ def Initialize(self): # Initialize GiD I/O (gid outputs, file_lists) self.SetGraphicalOutput() - + self.GraphicalOutputExecuteInitialize() print(" ") @@ -136,7 +136,7 @@ def Initialize(self): self.model_processes.ExecuteBeforeSolutionLoop() - self.GraphicalOutputExecuteBeforeSolutionLoop() + self.GraphicalOutputExecuteBeforeSolutionLoop() # Set time settings self.step = self.main_model_part.ProcessInfo[KratosMultiphysics.STEP] diff --git a/applications/FemToDemApplication/tests/fracture_tests/three_point_bending/fifth_notched_400mmDEM.mdpa b/applications/FemToDemApplication/tests/fracture_tests/three_point_bending/fifth_notched_400mmDEM.mdpa index 07b6c92699d4..00d63e2a4f7d 100644 --- a/applications/FemToDemApplication/tests/fracture_tests/three_point_bending/fifth_notched_400mmDEM.mdpa +++ b/applications/FemToDemApplication/tests/fracture_tests/three_point_bending/fifth_notched_400mmDEM.mdpa @@ -3,12 +3,13 @@ Begin Properties 1 PARTICLE_DENSITY 2500.00 YOUNG_MODULUS 1.00e9 POISSON_RATIO 0.2 - DYNAMIC_FRICTION 0.5773502691896257 STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 PARTICLE_COHESION 0.0 COEFFICIENT_OF_RESTITUTION 0.1 PARTICLE_MATERIAL 1 ROLLING_FRICTION 0.1 + FRICTION_DECAY 500 DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Linear_viscous_Coulomb DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw End Properties diff --git a/applications/FemToDemApplication/tests/fsi_tests/wall_2d/fsiDEM.mdpa b/applications/FemToDemApplication/tests/fsi_tests/wall_2d/fsiDEM.mdpa index 07b6c92699d4..00d63e2a4f7d 100644 --- a/applications/FemToDemApplication/tests/fsi_tests/wall_2d/fsiDEM.mdpa +++ b/applications/FemToDemApplication/tests/fsi_tests/wall_2d/fsiDEM.mdpa @@ -3,12 +3,13 @@ Begin Properties 1 PARTICLE_DENSITY 2500.00 YOUNG_MODULUS 1.00e9 POISSON_RATIO 0.2 - DYNAMIC_FRICTION 0.5773502691896257 STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 PARTICLE_COHESION 0.0 COEFFICIENT_OF_RESTITUTION 0.1 PARTICLE_MATERIAL 1 ROLLING_FRICTION 0.1 + FRICTION_DECAY 500 DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Linear_viscous_Coulomb DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw End Properties diff --git a/applications/FemToDemApplication/tests/small_tests/free_fall_contact/free_fall_contactDEM.mdpa b/applications/FemToDemApplication/tests/small_tests/free_fall_contact/free_fall_contactDEM.mdpa index febd27181e33..5bbeaa077d87 100644 --- a/applications/FemToDemApplication/tests/small_tests/free_fall_contact/free_fall_contactDEM.mdpa +++ b/applications/FemToDemApplication/tests/small_tests/free_fall_contact/free_fall_contactDEM.mdpa @@ -3,12 +3,13 @@ Begin Properties 1 PARTICLE_DENSITY 1.0 YOUNG_MODULUS 1.5e6 POISSON_RATIO 0.2 - DYNAMIC_FRICTION 0.5773502691896257 STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 PARTICLE_COHESION 0.0 COEFFICIENT_OF_RESTITUTION 0.9 PARTICLE_MATERIAL 1 ROLLING_FRICTION 0.1 + FRICTION_DECAY 500 DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Linear_viscous_Coulomb DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw End Properties diff --git a/applications/FemToDemApplication/tests/small_tests/pressure_face_load/face_loadDEM.mdpa b/applications/FemToDemApplication/tests/small_tests/pressure_face_load/face_loadDEM.mdpa index 07b6c92699d4..25dbed503430 100644 --- a/applications/FemToDemApplication/tests/small_tests/pressure_face_load/face_loadDEM.mdpa +++ b/applications/FemToDemApplication/tests/small_tests/pressure_face_load/face_loadDEM.mdpa @@ -3,13 +3,14 @@ Begin Properties 1 PARTICLE_DENSITY 2500.00 YOUNG_MODULUS 1.00e9 POISSON_RATIO 0.2 - DYNAMIC_FRICTION 0.5773502691896257 STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 PARTICLE_COHESION 0.0 COEFFICIENT_OF_RESTITUTION 0.1 PARTICLE_MATERIAL 1 ROLLING_FRICTION 0.1 DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Linear_viscous_Coulomb + FRICTION_DECAY 500 DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw End Properties diff --git a/applications/FemToDemApplication/tests/small_tests/small_strain/small_test_damageDEM.mdpa b/applications/FemToDemApplication/tests/small_tests/small_strain/small_test_damageDEM.mdpa index 07b6c92699d4..00d63e2a4f7d 100644 --- a/applications/FemToDemApplication/tests/small_tests/small_strain/small_test_damageDEM.mdpa +++ b/applications/FemToDemApplication/tests/small_tests/small_strain/small_test_damageDEM.mdpa @@ -3,12 +3,13 @@ Begin Properties 1 PARTICLE_DENSITY 2500.00 YOUNG_MODULUS 1.00e9 POISSON_RATIO 0.2 - DYNAMIC_FRICTION 0.5773502691896257 STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 PARTICLE_COHESION 0.0 COEFFICIENT_OF_RESTITUTION 0.1 PARTICLE_MATERIAL 1 ROLLING_FRICTION 0.1 + FRICTION_DECAY 500 DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Linear_viscous_Coulomb DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw End Properties diff --git a/applications/FemToDemApplication/tests/small_tests/table_bc_imposition/small_test_damageDEM.mdpa b/applications/FemToDemApplication/tests/small_tests/table_bc_imposition/small_test_damageDEM.mdpa index 07b6c92699d4..00d63e2a4f7d 100644 --- a/applications/FemToDemApplication/tests/small_tests/table_bc_imposition/small_test_damageDEM.mdpa +++ b/applications/FemToDemApplication/tests/small_tests/table_bc_imposition/small_test_damageDEM.mdpa @@ -3,12 +3,13 @@ Begin Properties 1 PARTICLE_DENSITY 2500.00 YOUNG_MODULUS 1.00e9 POISSON_RATIO 0.2 - DYNAMIC_FRICTION 0.5773502691896257 STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 PARTICLE_COHESION 0.0 COEFFICIENT_OF_RESTITUTION 0.1 PARTICLE_MATERIAL 1 ROLLING_FRICTION 0.1 + FRICTION_DECAY 500 DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Linear_viscous_Coulomb DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw End Properties diff --git a/applications/FemToDemApplication/tests/small_tests/total_lagrangian/small_test_damageDEM.mdpa b/applications/FemToDemApplication/tests/small_tests/total_lagrangian/small_test_damageDEM.mdpa index 07b6c92699d4..00d63e2a4f7d 100644 --- a/applications/FemToDemApplication/tests/small_tests/total_lagrangian/small_test_damageDEM.mdpa +++ b/applications/FemToDemApplication/tests/small_tests/total_lagrangian/small_test_damageDEM.mdpa @@ -3,12 +3,13 @@ Begin Properties 1 PARTICLE_DENSITY 2500.00 YOUNG_MODULUS 1.00e9 POISSON_RATIO 0.2 - DYNAMIC_FRICTION 0.5773502691896257 STATIC_FRICTION 0.5773502691896257 + DYNAMIC_FRICTION 0.5773502691896257 PARTICLE_COHESION 0.0 COEFFICIENT_OF_RESTITUTION 0.1 PARTICLE_MATERIAL 1 ROLLING_FRICTION 0.1 + FRICTION_DECAY 500 DEM_DISCONTINUUM_CONSTITUTIVE_LAW_NAME DEM_D_Linear_viscous_Coulomb DEM_CONTINUUM_CONSTITUTIVE_LAW_NAME DEMContinuumConstitutiveLaw End Properties diff --git a/applications/FluidDynamicsApplication/CMakeLists.txt b/applications/FluidDynamicsApplication/CMakeLists.txt index 5161b58b3304..a1eb247d2f13 100644 --- a/applications/FluidDynamicsApplication/CMakeLists.txt +++ b/applications/FluidDynamicsApplication/CMakeLists.txt @@ -116,6 +116,12 @@ pybind11_add_module( KratosFluidDynamicsApplication MODULE THIN_LTO ${KRATOS_FLU target_link_libraries( KratosFluidDynamicsApplication PRIVATE KratosFluidDynamicsCore) set_target_properties( KratosFluidDynamicsApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosFluidDynamicsCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosFluidDynamicsApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + ############################################################################### # changing the .dll suffix to .pyd if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") @@ -127,12 +133,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosFluidDynamicsApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosFluidDynamicsCore) - cotire(KratosFluidDynamicsApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/FluidDynamicsApplication.py KratosMultiphysics/FluidDynamicsApplication/__init__.py ) diff --git a/applications/FluidDynamicsApplication/custom_processes/embedded_skin_visualization_process.cpp b/applications/FluidDynamicsApplication/custom_processes/embedded_skin_visualization_process.cpp index 8fd64183b765..bccc7ad895f8 100644 --- a/applications/FluidDynamicsApplication/custom_processes/embedded_skin_visualization_process.cpp +++ b/applications/FluidDynamicsApplication/custom_processes/embedded_skin_visualization_process.cpp @@ -90,11 +90,10 @@ ModelPart& EmbeddedSkinVisualizationProcess::CreateAndPrepareVisualizationModelP r_visualization_variables_list.Add(r_var); } - // Set the origin model part as temporary communicator - // This is required to perform all the IsDistributed checks that appear before creating the visualization mesh - // Note that these checks might be required outside this process (i.e. in the creation of the visualization mesh output) - // This will be updated by a proper one by the ParallelFillCommunicator after the creation of the visualization entities - r_visualization_model_part.SetCommunicator(r_origin_model_part.pGetCommunicator()); + // Create a communicator for the visualization model part as a clone of the origin model part + // Note that we are retrieving the data communicator from the origin one to keep it unique + const auto& r_data_communicator = r_origin_model_part.GetCommunicator().GetDataCommunicator(); + r_visualization_model_part.SetCommunicator(r_origin_model_part.GetCommunicator().Create(r_data_communicator)); // If MPI, add the PARTITION_INDEX variable to the visualization model part variables if (r_visualization_model_part.IsDistributed()) { @@ -546,7 +545,12 @@ void EmbeddedSkinVisualizationProcess::CreateVisualizationMesh() this->CreateVisualizationGeometries(); // If MPI, this creates the communication plan among processes - ParallelEnvironment::CreateFillCommunicator(mrVisualizationModelPart)->Execute(); + // If serial, it is only required to set the current mesh as local mesh in order to output the values + if (mrVisualizationModelPart.IsDistributed()) { + ParallelEnvironment::CreateFillCommunicator(mrVisualizationModelPart)->Execute(); + } else { + mrVisualizationModelPart.GetCommunicator().SetLocalMesh(mrVisualizationModelPart.pGetMesh(0)); + } // Initialize (allocate) non-historical variables InitializeNonHistoricalVariables(mVisualizationNonHistoricalScalarVariables); diff --git a/applications/FluidDynamicsApplication/python_scripts/navier_stokes_two_fluids_solver.py b/applications/FluidDynamicsApplication/python_scripts/navier_stokes_two_fluids_solver.py index ae1604e4e2c4..59312071dbe4 100644 --- a/applications/FluidDynamicsApplication/python_scripts/navier_stokes_two_fluids_solver.py +++ b/applications/FluidDynamicsApplication/python_scripts/navier_stokes_two_fluids_solver.py @@ -382,6 +382,24 @@ def _GetAccelerationLimitationUtility(self): self._acceleration_limitation_utility = self.__CreateAccelerationLimitationUtility() return self._acceleration_limitation_utility + def _GetRedistancingLinearSolver(self): + # A linear solver configured specifically for distance re-initialization process + if not hasattr(self, '_redistancing_linear_solver'): + self._redistancing_linear_solver = self._CreateLinearSolver() # TODO: add customized configuration + return self._redistancing_linear_solver + + def _GetLevelsetLinearSolver(self): + # A linear solver configured specifically for the level-set convection process + if not hasattr(self, '_levelset_linear_solver'): + self._levelset_linear_solver = self._CreateLinearSolver() # TODO: add customized configuration + return self._levelset_linear_solver + + def _GetSmoothingLinearSolver(self): + # A linear solver configured specifically for the distance smoothing process + if not hasattr(self, '_smoothing_linear_solver'): + self._smoothing_linear_solver = self._CreateLinearSolver() # TODO: add customized configuration + return self._smoothing_linear_solver + def _GetLevelSetConvectionProcess(self): if not hasattr(self, '_level_set_convection_process'): self._level_set_convection_process = self._CreateLevelSetConvectionProcess() @@ -447,7 +465,7 @@ def _CreateLevelSetConvectionProcess(self): else: raise Exception("The BFECC level set convection requires the Kratos ConvectionDiffusionApplication compilation.") else: - linear_solver = self._GetLinearSolver() + linear_solver = self._GetLevelsetLinearSolver() levelset_convection_settings = self.settings["levelset_convection_settings"] if domain_size == 2: @@ -476,7 +494,7 @@ def _CreateDistanceReinitializationProcess(self): # Construct the variational distance calculation process if (self._reinitialization_type == "variational"): maximum_iterations = 2 #TODO: Make this user-definable - linear_solver = self._GetLinearSolver() + linear_solver = self._GetRedistancingLinearSolver() computing_model_part = self.GetComputingModelPart() if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: distance_reinitialization_process = KratosMultiphysics.VariationalDistanceCalculationProcess2D( @@ -509,7 +527,7 @@ def _CreateDistanceReinitializationProcess(self): def _CreateDistanceSmoothingProcess(self): # construct the distance smoothing process - linear_solver = self._GetLinearSolver() + linear_solver = self._GetSmoothingLinearSolver() if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: distance_smoothing_process = KratosCFD.DistanceSmoothingProcess2D( self.main_model_part, diff --git a/applications/FluidDynamicsApplication/python_scripts/trilinos_adjoint_vmsmonolithic_solver.py b/applications/FluidDynamicsApplication/python_scripts/trilinos_adjoint_vmsmonolithic_solver.py index 6855a449d957..af751daf7ae0 100644 --- a/applications/FluidDynamicsApplication/python_scripts/trilinos_adjoint_vmsmonolithic_solver.py +++ b/applications/FluidDynamicsApplication/python_scripts/trilinos_adjoint_vmsmonolithic_solver.py @@ -42,7 +42,7 @@ def PrepareModelPart(self): def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): - self._epetra_communicator = TrilinosApplication.CreateCommunicator() + self._epetra_communicator = TrilinosApplication.CreateEpetraCommunicator(self.main_model_part.GetCommunicator().GetDataCommunicator()) return self._epetra_communicator def _CreateScheme(self): diff --git a/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_embedded_solver.py b/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_embedded_solver.py index a185fda345db..18202793c283 100644 --- a/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_embedded_solver.py +++ b/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_embedded_solver.py @@ -50,7 +50,7 @@ def PrepareModelPart(self): def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): - self._epetra_communicator = KratosTrilinos.CreateCommunicator() + self._epetra_communicator = KratosTrilinos.CreateEpetraCommunicator(self.main_model_part.GetCommunicator().GetDataCommunicator()) return self._epetra_communicator def _CreateScheme(self): diff --git a/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_solver_fractionalstep.py b/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_solver_fractionalstep.py index 9fe6412843e7..7efbd1e041f0 100755 --- a/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_solver_fractionalstep.py +++ b/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_solver_fractionalstep.py @@ -64,7 +64,7 @@ def Finalize(self): def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): - self._epetra_communicator = KratosTrilinos.CreateCommunicator() + self._epetra_communicator = KratosTrilinos.CreateEpetraCommunicator(self.main_model_part.GetCommunicator().GetDataCommunicator()) return self._epetra_communicator def _CreateScheme(self): diff --git a/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_solver_vmsmonolithic.py b/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_solver_vmsmonolithic.py index cc1e887c76c4..26507611d9be 100755 --- a/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_solver_vmsmonolithic.py +++ b/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_solver_vmsmonolithic.py @@ -53,7 +53,7 @@ def Finalize(self): def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): - self._epetra_communicator = KratosTrilinos.CreateCommunicator() + self._epetra_communicator = KratosTrilinos.CreateEpetraCommunicator(self.main_model_part.GetCommunicator().GetDataCommunicator()) return self._epetra_communicator def _CreateScheme(self): diff --git a/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_two_fluids_solver.py b/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_two_fluids_solver.py index f041c4965339..e104f242fbc2 100755 --- a/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_two_fluids_solver.py +++ b/applications/FluidDynamicsApplication/python_scripts/trilinos_navier_stokes_two_fluids_solver.py @@ -63,7 +63,7 @@ def PrepareModelPart(self): def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): - self._epetra_communicator = KratosTrilinos.CreateCommunicator() + self._epetra_communicator = KratosTrilinos.CreateEpetraCommunicator(self.main_model_part.GetCommunicator().GetDataCommunicator()) return self._epetra_communicator def _CreateScheme(self): @@ -141,7 +141,7 @@ def _CreateSolutionStrategy(self): def _CreateLevelSetConvectionProcess(self): # Construct the level set convection process domain_size = self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] - linear_solver = self._GetLinearSolver() + levelset_linear_solver = self._GetLevelsetLinearSolver() computing_model_part = self.GetComputingModelPart() epetra_communicator = self._GetEpetraCommunicator() @@ -150,13 +150,13 @@ def _CreateLevelSetConvectionProcess(self): level_set_convection_process = KratosTrilinos.TrilinosLevelSetConvectionProcess2D( epetra_communicator, computing_model_part, - linear_solver, + levelset_linear_solver, levelset_convection_settings) else: level_set_convection_process = KratosTrilinos.TrilinosLevelSetConvectionProcess3D( epetra_communicator, computing_model_part, - linear_solver, + levelset_linear_solver, levelset_convection_settings) return level_set_convection_process @@ -164,22 +164,22 @@ def _CreateLevelSetConvectionProcess(self): def _CreateDistanceReinitializationProcess(self): # Construct the variational distance calculation process maximum_iterations = 2 #TODO: Make this user-definable - linear_solver = self._GetLinearSolver() + redistancing_linear_solver = self._GetRedistancingLinearSolver() computing_model_part = self.GetComputingModelPart() epetra_communicator = self._GetEpetraCommunicator() if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: variational_distance_process = KratosTrilinos.TrilinosVariationalDistanceCalculationProcess2D( epetra_communicator, computing_model_part, - linear_solver, + redistancing_linear_solver, maximum_iterations, KratosMultiphysics.VariationalDistanceCalculationProcess2D.CALCULATE_EXACT_DISTANCES_TO_PLANE) else: variational_distance_process = KratosTrilinos.TrilinosVariationalDistanceCalculationProcess3D( epetra_communicator, computing_model_part, - linear_solver, + redistancing_linear_solver, maximum_iterations, KratosMultiphysics.VariationalDistanceCalculationProcess3D.CALCULATE_EXACT_DISTANCES_TO_PLANE) - return variational_distance_process + return variational_distance_process \ No newline at end of file diff --git a/applications/FluidDynamicsApplication/tests/TwoFluidDarcyTest/solver_settings.json b/applications/FluidDynamicsApplication/tests/TwoFluidDarcyTest/solver_settings.json index b7c77b664afd..3a5bef70e82f 100644 --- a/applications/FluidDynamicsApplication/tests/TwoFluidDarcyTest/solver_settings.json +++ b/applications/FluidDynamicsApplication/tests/TwoFluidDarcyTest/solver_settings.json @@ -34,6 +34,7 @@ "time_stepping" : { "automatic_time_step" : false, "time_step" : 1.0 - } + }, + "distance_reinitialization": "none" } } \ No newline at end of file diff --git a/applications/FluidDynamicsApplication/trilinos_extension/CMakeLists.txt b/applications/FluidDynamicsApplication/trilinos_extension/CMakeLists.txt index 3717a9e57003..e06e25acd501 100644 --- a/applications/FluidDynamicsApplication/trilinos_extension/CMakeLists.txt +++ b/applications/FluidDynamicsApplication/trilinos_extension/CMakeLists.txt @@ -25,6 +25,11 @@ pybind11_add_module( KratosFluidDynamicsTrilinosExtension MODULE THIN_LTO ${KRAT target_link_libraries( KratosFluidDynamicsTrilinosExtension PRIVATE KratosFluidDynamicsCore KratosTrilinosCore KratosMPICore ${TRILINOS_LIBRARIES}) set_target_properties( KratosFluidDynamicsTrilinosExtension PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosFluidDynamicsTrilinosExtension PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + ############################################################################### # changing the .dll suffix to .pyd if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") @@ -36,10 +41,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosFluidDynamicsTrilinosExtension PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -if(USE_COTIRE MATCHES ON) - cotire(KratosFluidDynamicsTrilinosExtension) -endif(USE_COTIRE MATCHES ON) - ############################################################################### ## installing the resulting libraries install(TARGETS KratosFluidDynamicsTrilinosExtension DESTINATION libs ) diff --git a/applications/FluidTransportApplication/CMakeLists.txt b/applications/FluidTransportApplication/CMakeLists.txt index 110e25510a6b..66e1ec7cb6d6 100644 --- a/applications/FluidTransportApplication/CMakeLists.txt +++ b/applications/FluidTransportApplication/CMakeLists.txt @@ -38,6 +38,12 @@ pybind11_add_module(KratosFluidTransportApplication MODULE ${KRATOS_FLUID_TRANSP target_link_libraries(KratosFluidTransportApplication PRIVATE KratosFluidTransportCore) set_target_properties(KratosFluidTransportApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosFluidTransportCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosFluidTransportApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + ############################################################################### # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") @@ -49,12 +55,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosFluidTransportApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosFluidTransportCore) - cotire(KratosFluidTransportApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/FluidTransportApplication.py KratosMultiphysics/FluidTransportApplication/__init__.py ) diff --git a/applications/FreeSurfaceApplication/CMakeLists.txt b/applications/FreeSurfaceApplication/CMakeLists.txt index 536667e52d6e..fa5cf657b1a6 100644 --- a/applications/FreeSurfaceApplication/CMakeLists.txt +++ b/applications/FreeSurfaceApplication/CMakeLists.txt @@ -29,6 +29,12 @@ pybind11_add_module(KratosFreeSurfaceApplication MODULE THIN_LTO ${KRATOS_FREE_S target_link_libraries(KratosFreeSurfaceApplication PRIVATE KratosFreeSurfaceCore ) set_target_properties(KratosFreeSurfaceApplication PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosFreeSurfaceCore PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosFreeSurfaceApplication PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosFreeSurfaceApplication PROPERTIES SUFFIX .pyd) @@ -39,12 +45,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosFreeSurfaceApplication PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosFreeSurfaceCore) - cotire(KratosFreeSurfaceApplication) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/FreeSurfaceApplication.py KratosMultiphysics/FreeSurfaceApplication/__init__.py ) diff --git a/applications/FreeSurfaceApplication/custom_utilities/edgebased_gid_io.h b/applications/FreeSurfaceApplication/custom_utilities/edgebased_gid_io.h index de6f10f2eda5..8c58c7f13d3e 100644 --- a/applications/FreeSurfaceApplication/custom_utilities/edgebased_gid_io.h +++ b/applications/FreeSurfaceApplication/custom_utilities/edgebased_gid_io.h @@ -89,7 +89,7 @@ class EdgebasedGidGaussPointsContainer : public GidGaussPointsContainer for( ModelPart::ElementsContainerType::iterator it = mMeshElements.begin(); it != mMeshElements.end(); it++ ) { - it->GetValueOnIntegrationPoints( rVariable, ValuesOnIntPoint, + it->CalculateOnIntegrationPoints( rVariable, ValuesOnIntPoint, rModelPart.GetProcessInfo() ); for(unsigned int i=0; iGetValueOnIntegrationPoints( rVariable, ValuesOnIntPoint, + it->CalculateOnIntegrationPoints( rVariable, ValuesOnIntPoint, rModelPart.GetProcessInfo() ); for(unsigned int i=0; iGetValueOnIntegrationPoints( rVariable, ValuesOnIntPoint, + it->CalculateOnIntegrationPoints( rVariable, ValuesOnIntPoint, rModelPart.GetProcessInfo() ); for(unsigned int i=0; iGetValueOnIntegrationPoints( rVariable, ValuesOnIntPoint, + it->CalculateOnIntegrationPoints( rVariable, ValuesOnIntPoint, rModelPart.GetProcessInfo() ); for(unsigned int i=0; iGetValueOnIntegrationPoints( rVariable, ValuesOnIntPoint, + it->CalculateOnIntegrationPoints( rVariable, ValuesOnIntPoint, rModelPart.GetProcessInfo() ); for(unsigned int i=0; iGetValueOnIntegrationPoints( rVariable, ValuesOnIntPoint, + it->CalculateOnIntegrationPoints( rVariable, ValuesOnIntPoint, rModelPart.GetProcessInfo() ); for(unsigned int i=0; i0 procedure, Quasi-static, dynamic + +- Staged analysis + +- Automatic time stepping + +- UPw small displacement element for saturated porous media (with +equal order interpolation, unstable under incompressible-undrained +conditions) + +- Stable UPw small displacement element for saturated porous media +(with higher order interpolation for displacements) + +- FIC-Stabilized UPw small displacement element for saturated porous media +(with equal order interpolation for displacements) + +- UPw Quasi-zero-thickness interface elements for defining cracks and +joints + +- UPw Updated-Lagrangian element for saturated porous media (with +equal order interpolation, unstable under incompressible-undrained +conditions) + +- Stable UPw Updated-Lagrangian element for saturated porous media +(with higher order interpolation for displacements) + +- Reading and using dll/so of User Defined Soil Models (UDSM) based on PLAXIS forrmat + +- Reading and using dll/so of UMAT based on ABAQUS forrmat + +### How to compile Geo-Mechanics Application + +Make sure that the following lines are properly set in the configuration file: + +#### Windows: +~~~ +CALL :add_app %KRATOS_APP_DIR%\LinearSolversApplication; +CALL :add_app %KRATOS_APP_DIR%\StructuralMechanicsApplication; +CALL :add_app %KRATOS_APP_DIR%\GeoMechanicsApplication; +~~~ + +#### Linux: +~~~ +add_app ${KRATOS_APP_DIR}/LinearSolversApplication; +add_app ${KRATOS_APP_DIR}/StructuralMechanicsApplication; +add_app ${KRATOS_APP_DIR}/GeoMechanicsApplication; +~~~ + +*Note*: For the moment, MPI does not work. diff --git a/applications/GeoMechanicsApplication/custom_python/geo_mechanics_python_application.cpp b/applications/GeoMechanicsApplication/custom_python/geo_mechanics_python_application.cpp new file mode 100644 index 000000000000..22513970fb22 --- /dev/null +++ b/applications/GeoMechanicsApplication/custom_python/geo_mechanics_python_application.cpp @@ -0,0 +1,96 @@ +// KRATOS___ +// // ) ) +// // ___ ___ +// // ____ //___) ) // ) ) +// // / / // // / / +// ((____/ / ((____ ((___/ / MECHANICS +// +// License: geo_mechanics_application/license.txt +// +// Main authors: Ignasi de Pouplana, +// Vahid Galavi +// + +// System includes + +#if defined(KRATOS_PYTHON) + +// External includes +#include + + +// Project includes +#include "includes/define_python.h" + + +// Application includes +#include "geo_mechanics_application.h" +#include "geo_mechanics_application_variables.h" + + +namespace Kratos { +namespace Python { + + using namespace pybind11; + + PYBIND11_MODULE(KratosGeoMechanicsApplication,m) + { + + class_(m, "KratosGeoMechanicsApplication") + .def(init<>()); + + + + //Registering variables in python + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, VELOCITY_COEFFICIENT ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, DT_PRESSURE_COEFFICIENT ) + + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, DT_WATER_PRESSURE ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, NORMAL_FLUID_FLUX ) + + KRATOS_REGISTER_IN_PYTHON_3D_VARIABLE_WITH_COMPONENTS( m, FLUID_FLUX_VECTOR ) + KRATOS_REGISTER_IN_PYTHON_3D_VARIABLE_WITH_COMPONENTS( m, LOCAL_FLUID_FLUX_VECTOR ) + KRATOS_REGISTER_IN_PYTHON_3D_VARIABLE_WITH_COMPONENTS( m, LOCAL_STRESS_VECTOR ) + KRATOS_REGISTER_IN_PYTHON_3D_VARIABLE_WITH_COMPONENTS( m, LOCAL_RELATIVE_DISPLACEMENT_VECTOR ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, PERMEABILITY_MATRIX ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, LOCAL_PERMEABILITY_MATRIX ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, TOTAL_STRESS_TENSOR ) + + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, DEGREE_OF_SATURATION ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, EFFECTIVE_SATURATION ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, BISHOP_COEFICIENT ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, DERIVATIVE_OF_SATURATION ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, RELATIVE_PERMEABILITY ) + + KRATOS_REGISTER_IN_PYTHON_3D_VARIABLE_WITH_COMPONENTS( m, TOTAL_DISPLACEMENT) + + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, IS_CONVERGED ) + + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, ARC_LENGTH_LAMBDA ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, ARC_LENGTH_RADIUS_FACTOR ) + + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, TIME_UNIT_CONVERTER ) + + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, JOINT_WIDTH ) + + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, NODAL_SMOOTHING ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, NODAL_CAUCHY_STRESS_TENSOR ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, NODAL_DAMAGE_VARIABLE ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, NODAL_JOINT_AREA ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, NODAL_JOINT_WIDTH ) + KRATOS_REGISTER_IN_PYTHON_VARIABLE( m, NODAL_JOINT_DAMAGE ) + + /* Reset displacement "flag" needed for GeoMechanicalApplication*/ + KRATOS_REGISTER_IN_PYTHON_VARIABLE(m,RESET_DISPLACEMENTS); + + + + } + + +} // namespace Python. +} // namespace Kratos. + +#endif // KRATOS_PYTHON defined diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.aux b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.aux new file mode 100644 index 000000000000..f54d5a0b6dd1 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.aux @@ -0,0 +1,142 @@ +\relax +\providecommand\hyper@newdestlabel[2]{} +\providecommand\BKM@entry[2]{} +\providecommand{\transparent@use}[1]{} +\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument} +\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined +\global\let\oldcontentsline\contentsline +\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} +\global\let\oldnewlabel\newlabel +\gdef\newlabel#1#2{\newlabelxx{#1}#2} +\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} +\AtEndDocument{\ifx\hyper@anchor\@undefined +\let\contentsline\oldcontentsline +\let\newlabel\oldnewlabel +\fi} +\fi} +\global\let\hyper@last\relax +\gdef\HyperFirstAtBeginDocument#1{#1} +\providecommand\HyField@AuxAddToFields[1]{} +\providecommand\HyField@AuxAddToCoFields[2]{} +\bibstyle{deltares_chicago_like} +\babel@aux{english}{} +\BKM@entry{id=1,dest={636861707465722A2E32},srcline={53},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{4C697374206F662046696775726573} +\@writefile{toc}{\contentsline {chapter}{List of Figures}{v}{chapter*.2}\protected@file@percent } +\BKM@entry{id=2,dest={636861707465722A2E33},srcline={53},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{4C697374206F66205461626C6573} +\@writefile{toc}{\contentsline {chapter}{List of Tables}{vii}{chapter*.3}\protected@file@percent } +\BKM@entry{id=3,dest={636861707465722E31},srcline={55},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{3120496E74726F64756374696F6E} +\@writefile{toc}{\contentsline {chapter}{\numberline {1}Introduction}{1}{chapter.1}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\newlabel{intro}{{1}{1}{Introduction}{chapter.1}{}} +\BKM@entry{id=4,dest={636861707465722E32},srcline={59},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{322042656E63686D61726B20313A2042692D617869616C207368656172696E6720746573742077697468206C696E65617220656C6173746963206D6F64656C} +\BKM@entry{id=5,dest={73656374696F6E2E322E31},srcline={63},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{322E312047656F6D6574727920616E6420626F756E6461727920636F6E646974696F6E73} +\BKM@entry{id=6,dest={73656374696F6E2E322E32},srcline={106},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{322E32204D6174657269616C} +\@writefile{toc}{\contentsline {chapter}{\numberline {2}Benchmark 1: Bi-axial shearing test with linear elastic model}{3}{chapter.2}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\newlabel{chap:bench1}{{2}{3}{Benchmark 1: Bi-axial shearing test with linear elastic model}{chapter.2}{}} +\@writefile{toc}{\contentsline {section}{\numberline {2.1}Geometry and boundary conditions}{3}{section.2.1}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {2.1}{\ignorespaces Coordinates of square specimen\relax }}{3}{table.caption.4}\protected@file@percent } +\providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}} +\newlabel{tab:CoordinatesOfSquareSpeciment}{{2.1}{3}{Coordinates of square specimen\relax }{table.caption.4}{}} +\@writefile{lot}{\contentsline {table}{\numberline {2.2}{\ignorespaces Line Load inputs for benchmark 1\relax }}{3}{table.caption.5}\protected@file@percent } +\newlabel{tab:loadinputbench1}{{2.2}{3}{Line Load inputs for benchmark 1\relax }{table.caption.5}{}} +\BKM@entry{id=7,dest={73656374696F6E2E322E33},srcline={116},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{322E33204D6573682047656E65726174696F6E} +\BKM@entry{id=8,dest={73656374696F6E2E322E34},srcline={120},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{322E3420526573756C7473} +\@writefile{toc}{\contentsline {section}{\numberline {2.2}Material}{4}{section.2.2}\protected@file@percent } +\newlabel{fig:material_bm_1}{{\caption@xref {fig:material_bm_1}{ on input line 112}}{4}{Material}{figure.caption.6}{}} +\@writefile{lof}{\contentsline {figure}{\numberline {2.1}{\ignorespaces Material input of benchmark 1\relax }}{4}{figure.caption.6}\protected@file@percent } +\newlabel{fig:was:used:in:doc}{{2.1}{4}{Material input of benchmark 1\relax }{figure.caption.6}{}} +\@writefile{toc}{\contentsline {section}{\numberline {2.3}Mesh Generation}{4}{section.2.3}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {2.4}Results}{4}{section.2.4}\protected@file@percent } +\newlabel{eq:shearmoduluscalc}{{(2.1)}{4}{Results}{equation.2.4.1}{}} +\newlabel{eq:shearstraincalc}{{(2.2)}{4}{Results}{equation.2.4.2}{}} +\@writefile{lot}{\contentsline {table}{\numberline {2.3}{\ignorespaces Results of displacements for benchmark1 \relax }}{4}{table.caption.7}\protected@file@percent } +\newlabel{tab:Resultsbm1}{{2.3}{4}{Results of displacements for benchmark1 \relax }{table.caption.7}{}} +\newlabel{table:was:used:in:doc}{{2.3}{4}{Results of displacements for benchmark1 \relax }{table.caption.7}{}} +\BKM@entry{id=9,dest={636861707465722E33},srcline={149},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332042656E63686D61726B20323A2042656E64696E67206F6620706C61746573} +\BKM@entry{id=10,dest={73656374696F6E2E332E31},srcline={154},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332E312042656E64696E67206F6620706C617465207768656E20706F696E74206C6F6164206973206170706C696564} +\BKM@entry{id=11,dest={73756273656374696F6E2E332E312E31},srcline={155},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332E312E312047656F6D65747279} +\BKM@entry{id=12,dest={73756273656374696F6E2E332E312E32},srcline={177},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332E312E32204D6174657269616C} +\BKM@entry{id=13,dest={73756273656374696F6E2E332E312E33},srcline={188},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332E312E3320526573756C7473} +\@writefile{toc}{\contentsline {chapter}{\numberline {3}Benchmark 2: Bending of plates}{7}{chapter.3}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\newlabel{Bench2}{{3}{7}{Benchmark 2: Bending of plates}{chapter.3}{}} +\@writefile{toc}{\contentsline {section}{\numberline {3.1}Bending of plate when point load is applied}{7}{section.3.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.1.1}Geometry}{7}{subsection.3.1.1}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {3.1}{\ignorespaces Coordinates plate element\relax }}{7}{table.caption.8}\protected@file@percent } +\newlabel{tab:platebend2.1}{{3.1}{7}{Coordinates plate element\relax }{table.caption.8}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.1.2}Material}{7}{subsection.3.1.2}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {3.1}{\ignorespaces Beam element of benchmark 2\relax }}{7}{figure.caption.9}\protected@file@percent } +\newlabel{fig:beam_bm_2.1}{{3.1}{7}{Beam element of benchmark 2\relax }{figure.caption.9}{}} +\newlabel{fig:was:used:in:doc}{{3.1}{7}{Beam element of benchmark 2\relax }{figure.caption.9}{}} +\BKM@entry{id=14,dest={73656374696F6E2E332E32},srcline={212},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332E322042656E64696E67206F6620706C617465207768656E206C696E65206C6F6164206973206170706C696564} +\BKM@entry{id=15,dest={73756273656374696F6E2E332E322E31},srcline={213},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332E322E312047656F6D65747279} +\BKM@entry{id=16,dest={73756273656374696F6E2E332E322E32},srcline={234},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332E322E32204D6174657269616C} +\BKM@entry{id=17,dest={73756273656374696F6E2E332E322E33},srcline={245},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{332E322E3320526573756C7473} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.1.3}Results}{8}{subsection.3.1.3}\protected@file@percent } +\newlabel{eq:disp2.1}{{(3.1)}{8}{Results}{equation.3.1.1}{}} +\@writefile{lot}{\contentsline {table}{\numberline {3.2}{\ignorespaces Results of deflection for benchmark 2 with the application of point load \relax }}{8}{table.caption.10}\protected@file@percent } +\newlabel{tab:Resultsbm2.1}{{3.2}{8}{Results of deflection for benchmark 2 with the application of point load \relax }{table.caption.10}{}} +\newlabel{table:was:used:in:doc}{{3.2}{8}{Results of deflection for benchmark 2 with the application of point load \relax }{table.caption.10}{}} +\@writefile{toc}{\contentsline {section}{\numberline {3.2}Bending of plate when line load is applied}{8}{section.3.2}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.1}Geometry}{8}{subsection.3.2.1}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {3.3}{\ignorespaces Coordinates plate element\relax }}{8}{table.caption.11}\protected@file@percent } +\newlabel{tab:platebend2.2}{{3.3}{8}{Coordinates plate element\relax }{table.caption.11}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.2}Material}{8}{subsection.3.2.2}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.3}Results}{8}{subsection.3.2.3}\protected@file@percent } +\newlabel{eq:disp2.2}{{(3.2)}{8}{Results}{equation.3.2.2}{}} +\@writefile{lof}{\contentsline {figure}{\numberline {3.2}{\ignorespaces Beam element of benchmark 2\relax }}{9}{figure.caption.12}\protected@file@percent } +\newlabel{fig:beam_bm_2.2}{{3.2}{9}{Beam element of benchmark 2\relax }{figure.caption.12}{}} +\newlabel{fig:was:used:in:doc}{{3.2}{9}{Beam element of benchmark 2\relax }{figure.caption.12}{}} +\@writefile{lot}{\contentsline {table}{\numberline {3.4}{\ignorespaces Results of deflection for benchmark 2 with the application of line load \relax }}{9}{table.caption.13}\protected@file@percent } +\newlabel{tab:Resultsbm2.2}{{3.4}{9}{Results of deflection for benchmark 2 with the application of line load \relax }{table.caption.13}{}} +\newlabel{table:was:used:in:doc}{{3.4}{9}{Results of deflection for benchmark 2 with the application of line load \relax }{table.caption.13}{}} +\BKM@entry{id=18,dest={636861707465722E34},srcline={272},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{342042656E63686D61726B20333A20536D6F6F746820726967696420666F6F74696E67206F6E20656C617374696320736F696C} +\BKM@entry{id=19,dest={73656374696F6E2E342E31},srcline={275},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{342E312047656F6D65747279} +\BKM@entry{id=20,dest={73656374696F6E2E342E32},srcline={288},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{342E32204D6174657269616C} +\BKM@entry{id=21,dest={73656374696F6E2E342E33},srcline={295},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{342E33204D657368696E67} +\BKM@entry{id=22,dest={73656374696F6E2E342E34},srcline={299},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{342E3420526573756C7473} +\@writefile{toc}{\contentsline {chapter}{\numberline {4}Benchmark 3: Smooth rigid footing on elastic soil}{11}{chapter.4}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\@writefile{toc}{\contentsline {section}{\numberline {4.1}Geometry}{11}{section.4.1}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {4.1}{\ignorespaces Geometry and mesh of model\relax }}{11}{figure.caption.14}\protected@file@percent } +\newlabel{fig:rigid_footing__geometry_bm_3}{{4.1}{11}{Geometry and mesh of model\relax }{figure.caption.14}{}} +\newlabel{fig:was:used:in:doc}{{4.1}{11}{Geometry and mesh of model\relax }{figure.caption.14}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.2}Material}{11}{section.4.2}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {4.3}Meshing}{11}{section.4.3}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {4.4}Results}{11}{section.4.4}\protected@file@percent } +\newlabel{eq:reaction_force_analytical}{{(4.1)}{11}{Results}{equation.4.4.1}{}} +\@writefile{lot}{\contentsline {table}{\numberline {4.1}{\ignorespaces Results of reaction force for benchmark 3 with the application of a settlement \relax }}{11}{table.caption.15}\protected@file@percent } +\newlabel{tab:Resultsbm3}{{4.1}{11}{Results of reaction force for benchmark 3 with the application of a settlement \relax }{table.caption.15}{}} +\newlabel{table:was:used:in:doc}{{4.1}{11}{Results of reaction force for benchmark 3 with the application of a settlement \relax }{table.caption.15}{}} +\@writefile{lof}{\contentsline {figure}{\numberline {4.2}{\ignorespaces Vertical stress underneath rigid footing benchmark 3\relax }}{12}{figure.caption.16}\protected@file@percent } +\newlabel{fig:rigid_footing_bm_3}{{4.2}{12}{Vertical stress underneath rigid footing benchmark 3\relax }{figure.caption.16}{}} +\newlabel{fig:was:used:in:doc}{{4.2}{12}{Vertical stress underneath rigid footing benchmark 3\relax }{figure.caption.16}{}} +\BKM@entry{id=23,dest={636861707465722E35},srcline={333},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{352042656E63686D61726B20343A20314420636F6E736F6C69646174696F6E206F6E20656C617374696320736F696C} +\BKM@entry{id=24,dest={73656374696F6E2E352E31},srcline={336},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{352E312047656F6D65747279} +\BKM@entry{id=25,dest={73656374696F6E2E352E32},srcline={342},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{352E32204D6174657269616C73} +\BKM@entry{id=26,dest={73656374696F6E2E352E33},srcline={345},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{352E33204D657368696E67} +\BKM@entry{id=27,dest={73656374696F6E2E352E34},srcline={351},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{352E342043616C63756C6174696F6E} +\BKM@entry{id=28,dest={73656374696F6E2E352E35},srcline={365},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{352E3520526573756C7473} +\@writefile{toc}{\contentsline {chapter}{\numberline {5}Benchmark 4: 1D consolidation on elastic soil}{13}{chapter.5}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\@writefile{toc}{\contentsline {section}{\numberline {5.1}Geometry}{13}{section.5.1}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {5.2}Materials}{13}{section.5.2}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {5.3}Meshing}{13}{section.5.3}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {5.4}Calculation}{13}{section.5.4}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {5.1}{\ignorespaces Relative excess pore pressure versus relative height on different time steps\relax }}{13}{figure.caption.17}\protected@file@percent } +\newlabel{fig:1d_consolidation_bm_4}{{5.1}{13}{Relative excess pore pressure versus relative height on different time steps\relax }{figure.caption.17}{}} +\newlabel{fig:was:used:in:doc}{{5.1}{13}{Relative excess pore pressure versus relative height on different time steps\relax }{figure.caption.17}{}} +\@writefile{toc}{\contentsline {section}{\numberline {5.5}Results}{13}{section.5.5}\protected@file@percent } +\newlabel{eq:relative_excess_pore_pressure_analytical}{{(5.1)}{13}{Results}{equation.5.5.1}{}} +\BKM@entry{id=29,dest={636861707465722A2E3138},srcline={377},srcfile={4B7261746F735F566572696669636174696F6E2E746578}}{4269626C696F677261706879} +\bibdata{references/kratos_references} +\@writefile{toc}{\contentsline {chapter}{Bibliography}{15}{chapter*.18}\protected@file@percent } +\newlabel{LastPage}{{}{15}{}{page.15}{}} +\xdef\lastpage@lastpage{15} +\xdef\lastpage@lastpageHy{15} diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.bbl b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.bbl new file mode 100644 index 000000000000..2a791dbcc42e --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.bbl @@ -0,0 +1,8 @@ +\begin{thebibliography}{0} +\newcommand{\enquote}[1]{``#1''} +\expandafter\ifx\csname natexlab\endcsname\relax\def\natexlab#1{#1}\fi +\expandafter\ifx\csname url\endcsname\relax + \def\url#1{\texttt{#1}}\fi +\expandafter\ifx\csname urlprefix\endcsname\relax\def\urlprefix{URL }\fi + +\end{thebibliography} diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.blg b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.blg new file mode 100644 index 000000000000..d690e5b7a502 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.blg @@ -0,0 +1,5 @@ +This is BibTeX, Version 0.99dThe top-level auxiliary file: Kratos_Verification.aux +The style file: deltares_chicago_like.bst +I found no \citation commands---while reading file Kratos_Verification.aux +Database file #1: references/kratos_references.bib +(There was 1 error message) diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.ilg b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.ilg new file mode 100644 index 000000000000..9fdc07998cc9 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.ilg @@ -0,0 +1,8 @@ +This is makeindex, version 2.15 [MiKTeX 2.9.6960 64-bit] (kpathsea + Thai support). +Scanning style file C:/resources/latex/makeindex/deltares/deltares_nomentbl.ist............... +** Input style error (file = C:/resources/latex/makeindex/deltares/deltares_nomentbl.ist, line = 51): + -- Unknown specifier \endinput. +done (15 attributes redefined, 1 ignored). +Scanning input file Kratos_Verification.nlo...done (0 entries accepted, 0 rejected). +Nothing written in Kratos_Verification.nls. +Transcript written in Kratos_Verification.ilg. diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.lof b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.lof new file mode 100644 index 000000000000..7534853ed32c --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.lof @@ -0,0 +1,12 @@ +\babel@toc {english}{} +\addvspace {10\p@ } +\addvspace {10\p@ } +\contentsline {figure}{\numberline {2.1}{\ignorespaces Material input of benchmark 1\relax }}{4}{figure.caption.6}% +\addvspace {10\p@ } +\contentsline {figure}{\numberline {3.1}{\ignorespaces Beam element of benchmark 2\relax }}{7}{figure.caption.9}% +\contentsline {figure}{\numberline {3.2}{\ignorespaces Beam element of benchmark 2\relax }}{9}{figure.caption.12}% +\addvspace {10\p@ } +\contentsline {figure}{\numberline {4.1}{\ignorespaces Geometry and mesh of model\relax }}{11}{figure.caption.14}% +\contentsline {figure}{\numberline {4.2}{\ignorespaces Vertical stress underneath rigid footing benchmark 3\relax }}{12}{figure.caption.16}% +\addvspace {10\p@ } +\contentsline {figure}{\numberline {5.1}{\ignorespaces Relative excess pore pressure versus relative height on different time steps\relax }}{13}{figure.caption.17}% diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.log b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.log new file mode 100644 index 000000000000..69995cb15bf0 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.log @@ -0,0 +1,1767 @@ +This is pdfTeX, Version 3.14159265-2.6-1.40.20 (MiKTeX 2.9.6960 64-bit) (preloaded format=pdflatex 2019.2.18) 27 AUG 2019 17:56 +entering extended mode +**./Kratos_Verification.tex +(Kratos_Verification.tex +LaTeX2e <2018-12-01> +(C:/resources/latex\tex/latex/deltares\deltares_manual_style.cls +Document Class: deltares_manual_style 2011/07/26 v0.1 Deltares Manual style cla +ss +) (C:/resources/latex\tex/latex/deltares\deltares_manual.cls +Document Class: deltares_manual 2014/04/01 v1.0 Standard LaTeX document class +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\report.cls" +Document Class: report 2018/09/03 v1.4i Standard LaTeX document class +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\size11.clo" +File: size11.clo 2018/09/03 v1.4i Standard LaTeX file (size option) +) +\c@part=\count80 +\c@chapter=\count81 +\c@section=\count82 +\c@subsection=\count83 +\c@subsubsection=\count84 +\c@paragraph=\count85 +\c@subparagraph=\count86 +\c@figure=\count87 +\c@table=\count88 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/psnfss\helvet.st +y" +Package: helvet 2005/04/12 PSNFSS-v9.2a (WaS) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics\keyval. +sty" +Package: keyval 2014/10/28 v1.15 key=value parser (DPC) +\KV@toks@=\toks14 +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/sectsty\sectsty. +sty" +Package: sectsty 2002/02/25 v2.0.2 Commands to change all sectional heading sty +les +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\inputenc.st +y" +Package: inputenc 2018/08/11 v1.3c Input encoding file +\inpenc@prehook=\toks15 +\inpenc@posthook=\toks16 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\fontenc.sty +" +Package: fontenc 2018/08/11 v2.0j Standard LaTeX package + ("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\t1enc.def" +File: t1enc.def 2018/08/11 v2.0j Standard LaTeX file +LaTeX Font Info: Redeclaring font encoding T1 on input line 48. +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics\graphic +x.sty" +Package: graphicx 2017/06/01 v1.1a Enhanced LaTeX Graphics (DPC,SPQR) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics\graphic +s.sty" +Package: graphics 2017/06/25 v1.2c Standard LaTeX Graphics (DPC,SPQR) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics\trig.st +y" +Package: trig 2016/01/03 v1.10 sin cos tan (DPC) +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics-cfg\gra +phics.cfg" +File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration +) +Package graphics Info: Driver file: pdftex.def on input line 99. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics-def\pdf +tex.def" +File: pdftex.def 2018/01/08 v1.0l Graphics/color driver for pdftex +)) +\Gin@req@height=\dimen103 +\Gin@req@width=\dimen104 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\epstopd +f.sty" +Package: epstopdf 2016/05/15 v2.6 Conversion with epstopdf on the fly (HO) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\epstopd +f-base.sty" +Package: epstopdf-base 2016/05/15 v2.6 Base part for package epstopdf + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\infwa +rerr.sty" +Package: infwarerr 2016/05/16 v1.4 Providing info/warning/error messages (HO) +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\grfext. +sty" +Package: grfext 2016/05/16 v1.2 Manage graphics extensions (HO) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\kvdef +inekeys.sty" +Package: kvdefinekeys 2016/05/16 v1.4 Define keys (HO) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\ltxcm +ds.sty" +Package: ltxcmds 2016/05/16 v1.23 LaTeX kernel commands for general use (HO) +))) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\kvoptio +ns.sty" +Package: kvoptions 2016/05/16 v3.12 Key value format for package options (HO) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\kvset +keys.sty" +Package: kvsetkeys 2016/05/16 v1.17 Key value parser (HO) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\etexc +mds.sty" +Package: etexcmds 2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\iflua +tex.sty" +Package: ifluatex 2016/05/16 v1.4 Provides the ifluatex switch (HO) +Package ifluatex Info: LuaTeX not detected. +)))) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\pdfte +xcmds.sty" +Package: pdftexcmds 2018/09/10 v0.29 Utility functions of pdfTeX for LuaTeX (HO +) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\ifpdf +.sty" +Package: ifpdf 2018/09/07 v3.3 Provides the ifpdf switch +) +Package pdftexcmds Info: LuaTeX not detected. +Package pdftexcmds Info: \pdf@primitive is available. +Package pdftexcmds Info: \pdf@ifprimitive is available. +Package pdftexcmds Info: \pdfdraftmode found. +) +Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4 +38. +Package grfext Info: Graphics extension search list: +(grfext) [.pdf,.png,.jpg,.mps,.jpeg,.jbig2,.jb2,.PDF,.PNG,.JPG,.JPE +G,.JBIG2,.JB2,.eps] +(grfext) \AppendGraphicsExtensions on input line 456. +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics\color.s +ty" +Package: color 2016/07/10 v1.1e Standard LaTeX Color (DPC) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics-cfg\col +or.cfg" +File: color.cfg 2016/01/02 v1.6 sample color configuration +) +Package color Info: Driver file: pdftex.def on input line 147. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/frcursive\frcurs +ive.sty" +Package: frcursive 2004/02/01 v1.2 support package for French Cursive +\seyesThickness=\skip43 +\seyes@box=\box27 +\seyes@ln=\skip44 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/float\float.sty" +Package: float 2001/11/08 v1.3d Float enhancements (AL) +\c@float@type=\count89 +\float@exts=\toks17 +\float@box=\box28 +\@float@everytoks=\toks18 +\@floatcapt=\box29 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\textcomp.st +y" +Package: textcomp 2018/08/11 v2.0j Standard LaTeX package +Package textcomp Info: Sub-encoding information: +(textcomp) 5 = only ISO-Adobe without \textcurrency +(textcomp) 4 = 5 + \texteuro +(textcomp) 3 = 4 + \textohm +(textcomp) 2 = 3 + \textestimated + \textcurrency +(textcomp) 1 = TS1 - \textcircled - \t +(textcomp) 0 = TS1 (full) +(textcomp) Font families with sub-encoding setting implement +(textcomp) only a restricted character set as indicated. +(textcomp) Family '?' is the default used for unknown fonts. +(textcomp) See the documentation for details. +Package textcomp Info: Setting ? sub-encoding to TS1/1 on input line 79. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\ts1enc.def" +File: ts1enc.def 2001/06/05 v3.0e (jk/car/fm) Standard LaTeX file +Now handling font encoding TS1 ... +... processing UTF-8 mapping file for font encoding TS1 +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\ts1enc.dfu" +File: ts1enc.dfu 2018/10/05 v1.2f UTF-8 support for inputenc + defining Unicode char U+00A2 (decimal 162) + defining Unicode char U+00A3 (decimal 163) + defining Unicode char U+00A4 (decimal 164) + defining Unicode char U+00A5 (decimal 165) + defining Unicode char U+00A6 (decimal 166) + defining Unicode char U+00A7 (decimal 167) + defining Unicode char U+00A8 (decimal 168) + defining Unicode char U+00A9 (decimal 169) + defining Unicode char U+00AA (decimal 170) + defining Unicode char U+00AC (decimal 172) + defining Unicode char U+00AE (decimal 174) + defining Unicode char U+00AF (decimal 175) + defining Unicode char U+00B0 (decimal 176) + defining Unicode char U+00B1 (decimal 177) + defining Unicode char U+00B2 (decimal 178) + defining Unicode char U+00B3 (decimal 179) + defining Unicode char U+00B4 (decimal 180) + defining Unicode char U+00B5 (decimal 181) + defining Unicode char U+00B6 (decimal 182) + defining Unicode char U+00B7 (decimal 183) + defining Unicode char U+00B9 (decimal 185) + defining Unicode char U+00BA (decimal 186) + defining Unicode char U+00BC (decimal 188) + defining Unicode char U+00BD (decimal 189) + defining Unicode char U+00BE (decimal 190) + defining Unicode char U+00D7 (decimal 215) + defining Unicode char U+00F7 (decimal 247) + defining Unicode char U+0192 (decimal 402) + defining Unicode char U+02C7 (decimal 711) + defining Unicode char U+02D8 (decimal 728) + defining Unicode char U+02DD (decimal 733) + defining Unicode char U+0E3F (decimal 3647) + defining Unicode char U+2016 (decimal 8214) + defining Unicode char U+2020 (decimal 8224) + defining Unicode char U+2021 (decimal 8225) + defining Unicode char U+2022 (decimal 8226) + defining Unicode char U+2030 (decimal 8240) + defining Unicode char U+2031 (decimal 8241) + defining Unicode char U+203B (decimal 8251) + defining Unicode char U+203D (decimal 8253) + defining Unicode char U+2044 (decimal 8260) + defining Unicode char U+204E (decimal 8270) + defining Unicode char U+2052 (decimal 8274) + defining Unicode char U+20A1 (decimal 8353) + defining Unicode char U+20A4 (decimal 8356) + defining Unicode char U+20A6 (decimal 8358) + defining Unicode char U+20A9 (decimal 8361) + defining Unicode char U+20AB (decimal 8363) + defining Unicode char U+20AC (decimal 8364) + defining Unicode char U+20B1 (decimal 8369) + defining Unicode char U+2103 (decimal 8451) + defining Unicode char U+2116 (decimal 8470) + defining Unicode char U+2117 (decimal 8471) + defining Unicode char U+211E (decimal 8478) + defining Unicode char U+2120 (decimal 8480) + defining Unicode char U+2122 (decimal 8482) + defining Unicode char U+2126 (decimal 8486) + defining Unicode char U+2127 (decimal 8487) + defining Unicode char U+212E (decimal 8494) + defining Unicode char U+2190 (decimal 8592) + defining Unicode char U+2191 (decimal 8593) + defining Unicode char U+2192 (decimal 8594) + defining Unicode char U+2193 (decimal 8595) + defining Unicode char U+2329 (decimal 9001) + defining Unicode char U+232A (decimal 9002) + defining Unicode char U+2422 (decimal 9250) + defining Unicode char U+25E6 (decimal 9702) + defining Unicode char U+25EF (decimal 9711) + defining Unicode char U+266A (decimal 9834) + defining Unicode char U+FEFF (decimal 65279) +)) +LaTeX Info: Redefining \oldstylenums on input line 334. +Package textcomp Info: Setting cmr sub-encoding to TS1/0 on input line 349. +Package textcomp Info: Setting cmss sub-encoding to TS1/0 on input line 350. +Package textcomp Info: Setting cmtt sub-encoding to TS1/0 on input line 351. +Package textcomp Info: Setting cmvtt sub-encoding to TS1/0 on input line 352. +Package textcomp Info: Setting cmbr sub-encoding to TS1/0 on input line 353. +Package textcomp Info: Setting cmtl sub-encoding to TS1/0 on input line 354. +Package textcomp Info: Setting ccr sub-encoding to TS1/0 on input line 355. +Package textcomp Info: Setting ptm sub-encoding to TS1/4 on input line 356. +Package textcomp Info: Setting pcr sub-encoding to TS1/4 on input line 357. +Package textcomp Info: Setting phv sub-encoding to TS1/4 on input line 358. +Package textcomp Info: Setting ppl sub-encoding to TS1/3 on input line 359. +Package textcomp Info: Setting pag sub-encoding to TS1/4 on input line 360. +Package textcomp Info: Setting pbk sub-encoding to TS1/4 on input line 361. +Package textcomp Info: Setting pnc sub-encoding to TS1/4 on input line 362. +Package textcomp Info: Setting pzc sub-encoding to TS1/4 on input line 363. +Package textcomp Info: Setting bch sub-encoding to TS1/4 on input line 364. +Package textcomp Info: Setting put sub-encoding to TS1/5 on input line 365. +Package textcomp Info: Setting uag sub-encoding to TS1/5 on input line 366. +Package textcomp Info: Setting ugq sub-encoding to TS1/5 on input line 367. +Package textcomp Info: Setting ul8 sub-encoding to TS1/4 on input line 368. +Package textcomp Info: Setting ul9 sub-encoding to TS1/4 on input line 369. +Package textcomp Info: Setting augie sub-encoding to TS1/5 on input line 370. +Package textcomp Info: Setting dayrom sub-encoding to TS1/3 on input line 371. +Package textcomp Info: Setting dayroms sub-encoding to TS1/3 on input line 372. + +Package textcomp Info: Setting pxr sub-encoding to TS1/0 on input line 373. +Package textcomp Info: Setting pxss sub-encoding to TS1/0 on input line 374. +Package textcomp Info: Setting pxtt sub-encoding to TS1/0 on input line 375. +Package textcomp Info: Setting txr sub-encoding to TS1/0 on input line 376. +Package textcomp Info: Setting txss sub-encoding to TS1/0 on input line 377. +Package textcomp Info: Setting txtt sub-encoding to TS1/0 on input line 378. +Package textcomp Info: Setting lmr sub-encoding to TS1/0 on input line 379. +Package textcomp Info: Setting lmdh sub-encoding to TS1/0 on input line 380. +Package textcomp Info: Setting lmss sub-encoding to TS1/0 on input line 381. +Package textcomp Info: Setting lmssq sub-encoding to TS1/0 on input line 382. +Package textcomp Info: Setting lmvtt sub-encoding to TS1/0 on input line 383. +Package textcomp Info: Setting lmtt sub-encoding to TS1/0 on input line 384. +Package textcomp Info: Setting qhv sub-encoding to TS1/0 on input line 385. +Package textcomp Info: Setting qag sub-encoding to TS1/0 on input line 386. +Package textcomp Info: Setting qbk sub-encoding to TS1/0 on input line 387. +Package textcomp Info: Setting qcr sub-encoding to TS1/0 on input line 388. +Package textcomp Info: Setting qcs sub-encoding to TS1/0 on input line 389. +Package textcomp Info: Setting qpl sub-encoding to TS1/0 on input line 390. +Package textcomp Info: Setting qtm sub-encoding to TS1/0 on input line 391. +Package textcomp Info: Setting qzc sub-encoding to TS1/0 on input line 392. +Package textcomp Info: Setting qhvc sub-encoding to TS1/0 on input line 393. +Package textcomp Info: Setting futs sub-encoding to TS1/4 on input line 394. +Package textcomp Info: Setting futx sub-encoding to TS1/4 on input line 395. +Package textcomp Info: Setting futj sub-encoding to TS1/4 on input line 396. +Package textcomp Info: Setting hlh sub-encoding to TS1/3 on input line 397. +Package textcomp Info: Setting hls sub-encoding to TS1/3 on input line 398. +Package textcomp Info: Setting hlst sub-encoding to TS1/3 on input line 399. +Package textcomp Info: Setting hlct sub-encoding to TS1/5 on input line 400. +Package textcomp Info: Setting hlx sub-encoding to TS1/5 on input line 401. +Package textcomp Info: Setting hlce sub-encoding to TS1/5 on input line 402. +Package textcomp Info: Setting hlcn sub-encoding to TS1/5 on input line 403. +Package textcomp Info: Setting hlcw sub-encoding to TS1/5 on input line 404. +Package textcomp Info: Setting hlcf sub-encoding to TS1/5 on input line 405. +Package textcomp Info: Setting pplx sub-encoding to TS1/3 on input line 406. +Package textcomp Info: Setting pplj sub-encoding to TS1/3 on input line 407. +Package textcomp Info: Setting ptmx sub-encoding to TS1/4 on input line 408. +Package textcomp Info: Setting ptmj sub-encoding to TS1/4 on input line 409. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/pdfpages\pdfpage +s.sty" +Package: pdfpages 2017/10/31 v0.5l Insert pages of external PDF documents (AM) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\ifthen.sty" +Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC) +) ("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tools\calc.sty +" +Package: calc 2017/05/25 v4.3 Infix arithmetic (KKT,FJ) +\calc@Acount=\count90 +\calc@Bcount=\count91 +\calc@Adimen=\dimen105 +\calc@Bdimen=\dimen106 +\calc@Askip=\skip45 +\calc@Bskip=\skip46 +LaTeX Info: Redefining \setlength on input line 80. +LaTeX Info: Redefining \addtolength on input line 81. +\calc@Ccount=\count92 +\calc@Cskip=\skip47 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/eso-pic\eso-pic. +sty" +Package: eso-pic 2018/04/12 v2.0h eso-pic (RN) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\atbeg +shi.sty" +Package: atbegshi 2016/06/09 v1.18 At begin shipout hook (HO) +)) +\AM@pagewidth=\dimen107 +\AM@pageheight=\dimen108 + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/pdfpages\pppdfte +x.def" +File: pppdftex.def 2017/10/31 v0.5l Pdfpages driver for pdfTeX (AM) +) +\AM@pagebox=\box30 +\AM@global@opts=\toks19 +\AM@toc@title=\toks20 +\c@AM@survey=\count93 +\AM@templatesizebox=\box31 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/babel\babel.st +y" +Package: babel 2018/11/13 3.27 The Babel package + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/babel\switch.d +ef" +File: switch.def 2018/11/13 3.27 Babel switching mechanism +) +************************************* +* Local config file bblopts.cfg used +* + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/arabi\bblopts.cf +g" +File: bblopts.cfg 2005/09/08 v0.1 add Arabic and Farsi to "declared" options of + babel +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/babel-english\en +glish.ldf" +Language: english 2017/06/06 v3.3r English support from the babel system + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/babel\babel.de +f" +File: babel.def 2018/11/13 3.27 Babel common definitions +\babel@savecnt=\count94 +\U@D=\dimen109 + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/babel\txtbabel +.def") +\bbl@dirlevel=\count95 +) +\l@canadian = a dialect from \language\l@american +\l@australian = a dialect from \language\l@british +\l@newzealand = a dialect from \language\l@british +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/svn-multi\svn-mu +lti.sty" +Package: svn-multi 2011/08/30 v2.4d SVN Keywords for multi-file LaTeX documents + +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tools\tabularx.s +ty" +Package: tabularx 2016/02/03 v2.11b `tabularx' package (DPC) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tools\array.sty" +Package: array 2018/12/30 v2.4k Tabular extension package (FMi) +\col@sep=\dimen110 +\ar@mcellbox=\box32 +\extrarowheight=\dimen111 +\NC@list=\toks21 +\extratabsurround=\skip48 +\backup@length=\skip49 +\ar@cellbox=\box33 +) +\TX@col@width=\dimen112 +\TX@old@table=\dimen113 +\TX@old@col=\dimen114 +\TX@target=\dimen115 +\TX@delta=\dimen116 +\TX@cols=\count96 +\TX@ftn=\toks22 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tools\longtable. +sty" +Package: longtable 2014/10/28 v4.11 Multi-page Table package (DPC)+ FMi change +\LTleft=\skip50 +\LTright=\skip51 +\LTpre=\skip52 +\LTpost=\skip53 +\LTchunksize=\count97 +\LTcapwidth=\dimen117 +\LT@head=\box34 +\LT@firsthead=\box35 +\LT@foot=\box36 +\LT@lastfoot=\box37 +\LT@cols=\count98 +\LT@rows=\count99 +\c@LT@tables=\count100 +\c@LT@chunks=\count101 +\LT@p@ftn=\toks23 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tools\verbatim.s +ty" +Package: verbatim 2014/10/28 v1.5q LaTeX2e package for verbatim enhancements +\every@verbatim=\toks24 +\verbatim@line=\toks25 +\verbatim@in@stream=\read1 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/fancyvrb\fancyvr +b.sty" +Package: fancyvrb 2019/01/15 + Style option: `fancyvrb' v3.2a <2019/01/15> (tvz) +\FV@CodeLineNo=\count102 +\FV@InFile=\read2 +\FV@TabBox=\box38 +\c@FancyVerbLine=\count103 +\FV@StepNumber=\count104 +\FV@OutFile=\write3 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/wrapfig\wrapfig. +sty" +\wrapoverhang=\dimen118 +\WF@size=\dimen119 +\c@WF@wrappedlines=\count105 +\WF@box=\box39 +\WF@everypar=\toks26 +Package: wrapfig 2003/01/31 v 3.6 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/caption\caption. +sty" +Package: caption 2018/10/06 v3.3-154 Customizing captions (AR) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/caption\caption3 +.sty" +Package: caption3 2018/09/12 v1.8c caption3 kernel (AR) +Package caption3 Info: TeX engine: e-TeX on input line 64. +\captionmargin=\dimen120 +\captionmargin@=\dimen121 +\captionwidth=\dimen122 +\caption@tempdima=\dimen123 +\caption@indent=\dimen124 +\caption@parindent=\dimen125 +\caption@hangindent=\dimen126 +) +\c@caption@flags=\count106 +\c@ContinuedFloat=\count107 +Package caption Info: float package is loaded. +Package caption Info: longtable package is loaded. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/caption\ltcaptio +n.sty" +Package: ltcaption 2018/08/26 v1.4-95 longtable captions (AR) +) +Package caption Info: wrapfig package is loaded. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/caption\subcapti +on.sty" +Package: subcaption 2018/05/01 v1.1-162 Sub-captions (AR) +\c@subfigure=\count108 +\c@subtable=\count109 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/url\url.sty" +\Urlmuskip=\muskip10 +Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/moreverb\morever +b.sty" +Package: moreverb 2008/06/03 v2.3a `more' verbatim facilities +\tab@position=\count110 +\tab@size=\count111 +\listing@line=\count112 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/moresize\moresiz +e.sty" +Package: moresize 1999/07/26 v1.9 (more font sizes) +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics\rotatin +g.sty" +Package: rotating 2016/08/11 v2.16d rotated objects in LaTeX +\c@r@tfl@t=\count113 +\rotFPtop=\skip54 +\rotFPbot=\skip55 +\rot@float@box=\box40 +\rot@mess@toks=\toks27 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/hyperref\nameref +.sty" +Package: nameref 2016/05/21 v2.44 Cross-referencing by name of section + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\refcoun +t.sty" +Package: refcount 2016/05/16 v3.5 Data extraction from label references (HO) +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\getti +tlestring.sty" +Package: gettitlestring 2016/05/16 v1.5 Cleanup title references (HO) +) +\c@section@level=\count114 +LaTeX Info: Redefining \ref on input line 355. +LaTeX Info: Redefining \pageref on input line 355. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/import\import.st +y" +Package: import 2009/03/23 v 5.1 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/marginnote\margi +nnote.sty" +Package: marginnote 2018/08/09 v1.4b non floating margin notes for LaTeX +\c@mn@abspage=\count115 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsmath\amstext. +sty" +Package: amstext 2000/06/29 v2.01 AMS text + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsmath\amsgen.s +ty" +File: amsgen.sty 1999/11/30 v2.0 generic functions +\@emptytoks=\toks28 +\ex@=\dimen127 +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsmath\amsmath. +sty" +Package: amsmath 2018/12/01 v2.17b AMS math features +\@mathmargin=\skip56 + +For additional information on amsmath, use the `?' option. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsmath\amsbsy.s +ty" +Package: amsbsy 1999/11/29 v1.2d Bold Symbols +\pmbraise@=\dimen128 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsmath\amsopn.s +ty" +Package: amsopn 2016/03/08 v2.02 operator names +) +\inf@bad=\count116 +LaTeX Info: Redefining \frac on input line 223. +\uproot@=\count117 +\leftroot@=\count118 +LaTeX Info: Redefining \overline on input line 385. +\classnum@=\count119 +\DOTSCASE@=\count120 +LaTeX Info: Redefining \ldots on input line 482. +LaTeX Info: Redefining \dots on input line 485. +LaTeX Info: Redefining \cdots on input line 606. +\Mathstrutbox@=\box41 +\strutbox@=\box42 +\big@size=\dimen129 +LaTeX Font Info: Redeclaring font encoding OML on input line 729. +LaTeX Font Info: Redeclaring font encoding OMS on input line 730. +\macc@depth=\count121 +\c@MaxMatrixCols=\count122 +\dotsspace@=\muskip11 +\c@parentequation=\count123 +\dspbrk@lvl=\count124 +\tag@help=\toks29 +\row@=\count125 +\column@=\count126 +\maxfields@=\count127 +\andhelp@=\toks30 +\eqnshift@=\dimen130 +\alignsep@=\dimen131 +\tagshift@=\dimen132 +\tagwidth@=\dimen133 +\totwidth@=\dimen134 +\lineht@=\dimen135 +\@envbody=\toks31 +\multlinegap=\skip57 +\multlinetaggap=\skip58 +\mathdisplay@stack=\toks32 +LaTeX Info: Redefining \[ on input line 2844. +LaTeX Info: Redefining \] on input line 2845. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsfonts\amssymb +.sty" +Package: amssymb 2013/01/14 v3.01 AMS font symbols + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsfonts\amsfont +s.sty" +Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support +\symAMSa=\mathgroup4 +\symAMSb=\mathgroup5 +LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' +(Font) U/euf/m/n --> U/euf/b/n on input line 106. +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/paralist\paralis +t.sty" +Package: paralist 2017/01/22 v2.7 Extended list environments +\pltopsep=\skip59 +\plpartopsep=\skip60 +\plitemsep=\skip61 +\plparsep=\skip62 +\pl@lab=\toks33 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/siunitx\siunitx. +sty" +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/l3kernel\expl3.s +ty" +Package: expl3 2019-05-07 L3 programming layer (loader) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/l3kernel\expl3-c +ode.tex" +Package: expl3 2019-05-07 L3 programming layer (code) +\c_max_int=\count128 +\l_tmpa_int=\count129 +\l_tmpb_int=\count130 +\g_tmpa_int=\count131 +\g_tmpb_int=\count132 +\g__kernel_prg_map_int=\count133 +\c__ior_term_ior=\count134 +\c_log_iow=\count135 +\l_iow_line_count_int=\count136 +\l__iow_line_target_int=\count137 +\l__iow_one_indent_int=\count138 +\l__iow_indent_int=\count139 +\c_zero_dim=\dimen136 +\c_max_dim=\dimen137 +\l_tmpa_dim=\dimen138 +\l_tmpb_dim=\dimen139 +\g_tmpa_dim=\dimen140 +\g_tmpb_dim=\dimen141 +\c_zero_skip=\skip63 +\c_max_skip=\skip64 +\l_tmpa_skip=\skip65 +\l_tmpb_skip=\skip66 +\g_tmpa_skip=\skip67 +\g_tmpb_skip=\skip68 +\c_zero_muskip=\muskip12 +\c_max_muskip=\muskip13 +\l_tmpa_muskip=\muskip14 +\l_tmpb_muskip=\muskip15 +\g_tmpa_muskip=\muskip16 +\g_tmpb_muskip=\muskip17 +\l_keys_choice_int=\count140 +\l__intarray_loop_int=\count141 +\c__intarray_sp_dim=\dimen142 +\g__intarray_font_int=\count142 +\c__fp_leading_shift_int=\count143 +\c__fp_middle_shift_int=\count144 +\c__fp_trailing_shift_int=\count145 +\c__fp_big_leading_shift_int=\count146 +\c__fp_big_middle_shift_int=\count147 +\c__fp_big_trailing_shift_int=\count148 +\c__fp_Bigg_leading_shift_int=\count149 +\c__fp_Bigg_middle_shift_int=\count150 +\c__fp_Bigg_trailing_shift_int=\count151 +\c__kernel_randint_max_int=\count152 +\g__fp_array_int=\count153 +\l__fp_array_loop_int=\count154 +\l__sort_length_int=\count155 +\l__sort_min_int=\count156 +\l__sort_top_int=\count157 +\l__sort_max_int=\count158 +\l__sort_true_max_int=\count159 +\l__sort_block_int=\count160 +\l__sort_begin_int=\count161 +\l__sort_end_int=\count162 +\l__sort_A_int=\count163 +\l__sort_B_int=\count164 +\l__sort_C_int=\count165 +\l__tl_analysis_normal_int=\count166 +\l__tl_analysis_index_int=\count167 +\l__tl_analysis_nesting_int=\count168 +\l__tl_analysis_type_int=\count169 +\l__regex_internal_a_int=\count170 +\l__regex_internal_b_int=\count171 +\l__regex_internal_c_int=\count172 +\l__regex_balance_int=\count173 +\l__regex_group_level_int=\count174 +\l__regex_mode_int=\count175 +\c__regex_cs_in_class_mode_int=\count176 +\c__regex_cs_mode_int=\count177 +\l__regex_catcodes_int=\count178 +\l__regex_default_catcodes_int=\count179 +\c__regex_catcode_D_int=\count180 +\c__regex_catcode_S_int=\count181 +\c__regex_catcode_L_int=\count182 +\c__regex_catcode_O_int=\count183 +\c__regex_catcode_A_int=\count184 +\c__regex_all_catcodes_int=\count185 +\l__regex_show_lines_int=\count186 +\l__regex_min_state_int=\count187 +\l__regex_max_state_int=\count188 +\l__regex_left_state_int=\count189 +\l__regex_right_state_int=\count190 +\l__regex_capturing_group_int=\count191 +\l__regex_min_pos_int=\count192 +\l__regex_max_pos_int=\count193 +\l__regex_curr_pos_int=\count194 +\l__regex_start_pos_int=\count195 +\l__regex_success_pos_int=\count196 +\l__regex_curr_char_int=\count197 +\l__regex_curr_catcode_int=\count198 +\l__regex_last_char_int=\count199 +\l__regex_case_changed_char_int=\count266 +\l__regex_curr_state_int=\count267 +\l__regex_step_int=\count268 +\l__regex_min_active_int=\count269 +\l__regex_max_active_int=\count270 +\l__regex_replacement_csnames_int=\count271 +\l__regex_match_count_int=\count272 +\l__regex_min_submatch_int=\count273 +\l__regex_submatch_int=\count274 +\l__regex_zeroth_submatch_int=\count275 +\g__regex_trace_regex_int=\count276 +\c_empty_box=\box43 +\l_tmpa_box=\box44 +\l_tmpb_box=\box45 +\g_tmpa_box=\box46 +\g_tmpb_box=\box47 +\l__box_top_dim=\dimen143 +\l__box_bottom_dim=\dimen144 +\l__box_left_dim=\dimen145 +\l__box_right_dim=\dimen146 +\l__box_top_new_dim=\dimen147 +\l__box_bottom_new_dim=\dimen148 +\l__box_left_new_dim=\dimen149 +\l__box_right_new_dim=\dimen150 +\l__box_internal_box=\box48 +\l__coffin_internal_box=\box49 +\l__coffin_internal_dim=\dimen151 +\l__coffin_offset_x_dim=\dimen152 +\l__coffin_offset_y_dim=\dimen153 +\l__coffin_x_dim=\dimen154 +\l__coffin_y_dim=\dimen155 +\l__coffin_x_prime_dim=\dimen156 +\l__coffin_y_prime_dim=\dimen157 +\c_empty_coffin=\box50 +\l__coffin_aligned_coffin=\box51 +\l__coffin_aligned_internal_coffin=\box52 +\l_tmpa_coffin=\box53 +\l_tmpb_coffin=\box54 +\g_tmpa_coffin=\box55 +\g_tmpb_coffin=\box56 +\l__coffin_bounding_shift_dim=\dimen158 +\l__coffin_left_corner_dim=\dimen159 +\l__coffin_right_corner_dim=\dimen160 +\l__coffin_bottom_corner_dim=\dimen161 +\l__coffin_top_corner_dim=\dimen162 +\l__coffin_scaled_total_height_dim=\dimen163 +\l__coffin_scaled_width_dim=\dimen164 +\c__coffin_empty_coffin=\box57 +\l__coffin_display_coffin=\box58 +\l__coffin_display_coord_coffin=\box59 +\l__coffin_display_pole_coffin=\box60 +\l__coffin_display_offset_dim=\dimen165 +\l__coffin_display_x_dim=\dimen166 +\l__coffin_display_y_dim=\dimen167 +\g__file_internal_ior=\read3 +\l__seq_internal_a_int=\count277 +\l__seq_internal_b_int=\count278 +\c__deprecation_minus_one=\count279 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/l3kernel\l3pdfmo +de.def" +File: l3pdfmode.def 2019-04-06 v L3 Experimental driver: PDF mode +\l__driver_color_stack_int=\count280 +\l__driver_pdf_tmp_box=\box61 +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/l3packages/xpars +e\xparse.sty" +Package: xparse 2019-05-03 L3 Experimental document command parser +\l__xparse_current_arg_int=\count281 +\g__xparse_grabber_int=\count282 +\l__xparse_m_args_int=\count283 +\l__xparse_v_nesting_int=\count284 +) +Package: siunitx 2018/05/17 v2.7s A comprehensive (SI) units package + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/l3packages/l3key +s2e\l3keys2e.sty" +Package: l3keys2e 2019-05-03 LaTeX2e option processing using LaTeX3 keys +) +\l__siunitx_tmp_box=\box62 +\l__siunitx_tmp_dim=\dimen168 +\l__siunitx_tmp_int=\count285 +\l__siunitx_number_mantissa_length_int=\count286 +\l__siunitx_number_uncert_length_int=\count287 +\l__siunitx_round_int=\count288 +\l__siunitx_process_decimal_int=\count289 +\l__siunitx_process_uncertainty_int=\count290 +\l__siunitx_process_fixed_int=\count291 +\l__siunitx_process_integer_min_int=\count292 +\l__siunitx_process_precision_int=\count293 +\l__siunitx_group_min_int=\count294 +\l__siunitx_angle_marker_box=\box63 +\l__siunitx_angle_unit_box=\box64 +\l__siunitx_angle_marker_dim=\dimen169 +\l__siunitx_angle_unit_dim=\dimen170 +\l__siunitx_unit_int=\count295 +\l__siunitx_unit_denominator_int=\count296 +\l__siunitx_unit_numerator_int=\count297 +\l__siunitx_unit_prefix_int=\count298 +\l__siunitx_unit_prefix_base_int=\count299 +\l__siunitx_unit_prefix_gram_int=\count300 +\l__siunitx_number_product_int=\count301 +\c__siunitx_one_fill_skip=\skip69 +\l__siunitx_table_unit_align_skip=\skip70 +\l__siunitx_table_exponent_dim=\dimen171 +\l__siunitx_table_integer_dim=\dimen172 +\l__siunitx_table_mantissa_dim=\dimen173 +\l__siunitx_table_marker_dim=\dimen174 +\l__siunitx_table_result_dim=\dimen175 +\l__siunitx_table_uncert_dim=\dimen176 +\l__siunitx_table_fill_pre_dim=\dimen177 +\l__siunitx_table_fill_post_dim=\dimen178 +\l__siunitx_table_fill_mid_dim=\dimen179 +\l__siunitx_table_pre_box=\box65 +\l__siunitx_table_post_box=\box66 +\l__siunitx_table_mantissa_box=\box67 +\l__siunitx_table_result_box=\box68 +\l__siunitx_table_number_align_skip=\skip71 +\l__siunitx_table_text_align_skip=\skip72 + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/translator\trans +lator.sty" +Package: translator 2018/01/04 v1.12 Easy translation of strings in LaTeX +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tools\xspace.sty +" +Package: xspace 2014/10/28 v1.13 Space after command names (DPC,MH) +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/colortbl\colortb +l.sty" +Package: colortbl 2018/12/12 v1.0d Color table columns (DPC) +\everycr=\toks34 +\minrowclearance=\skip73 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/lastpage\lastpag +e.sty" +Package: lastpage 2015/03/29 v1.2m Refers to last page's name (HMM; JPG) +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/etoolbox\etoolbo +x.sty" +Package: etoolbox 2018/08/19 v2.5f e-TeX tools for LaTeX (JAW) +\etb@tempcnta=\count302 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/nomencl\nomencl. +sty" +Package: nomencl 2019/02/08 v5.1 Nomenclature package + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/xkeyval\xkeyval. +sty" +Package: xkeyval 2014/12/03 v2.7a package option processing (HA) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/xkeyval\xkeyva +l.tex" +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/xkeyval\xkvuti +ls.tex" +\XKV@toks=\toks35 +\XKV@tempa@toks=\toks36 +) +\XKV@depth=\count303 +File: xkeyval.tex 2014/12/03 v2.7a key=value parser (HA) +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/koma-script\tocb +asic.sty" +Package: tocbasic 2019/02/01 v3.26b KOMA-Script package (handling toc-files) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/koma-script\scrb +ase.sty" +Package: scrbase 2019/02/01 v3.26b KOMA-Script package (KOMA-Script-independent + basics and keyval usage) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/koma-script\scrl +file.sty" +Package: scrlfile 2019/02/01 v3.26b KOMA-Script package (loading files) +)) +\scr@dte@tocline@numberwidth=\skip74 +\scr@dte@tocline@numbox=\box69 +) +Package tocbasic Info: setting babel extension for `nlo' on input line 24. +Package tocbasic Info: setting babel extension for `nls' on input line 25. +\nomlabelwidth=\dimen180 +\nom@tempdim=\dimen181 +\nomitemsep=\skip75 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/nomentbl\nomentb +l.sty" +Package: nomentbl 2006/04/14 v0.4 Nomenclature in a longtable environment +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\bookmar +k.sty" +Package: bookmark 2016/05/17 v1.26 PDF bookmarks (HO) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\pdfes +cape.sty" +Package: pdfescape 2016/05/16 v1.14 Implements pdfTeX's escape features (HO) +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/ifxetex\ifxete +x.sty" +Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\ifvte +x.sty" +Package: ifvtex 2016/05/16 v1.6 Detect VTeX and its facilities (HO) +Package ifvtex Info: VTeX not detected. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/hyperref\hyperre +f.sty" +Package: hyperref 2018/11/30 v6.88e Hypertext links for LaTeX + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\hobsu +b-hyperref.sty" +Package: hobsub-hyperref 2016/05/16 v1.14 Bundle oberdiek, subset hyperref (HO) + + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\hobsu +b-generic.sty" +Package: hobsub-generic 2016/05/16 v1.14 Bundle oberdiek, subset generic (HO) +Package: hobsub 2016/05/16 v1.14 Construct package bundles (HO) +Package hobsub Info: Skipping package `infwarerr' (already loaded). +Package hobsub Info: Skipping package `ltxcmds' (already loaded). +Package hobsub Info: Skipping package `ifluatex' (already loaded). +Package hobsub Info: Skipping package `ifvtex' (already loaded). +Package: intcalc 2016/05/16 v1.2 Expandable calculations with integers (HO) +Package hobsub Info: Skipping package `ifpdf' (already loaded). +Package hobsub Info: Skipping package `etexcmds' (already loaded). +Package hobsub Info: Skipping package `kvsetkeys' (already loaded). +Package hobsub Info: Skipping package `kvdefinekeys' (already loaded). +Package hobsub Info: Skipping package `pdftexcmds' (already loaded). +Package hobsub Info: Skipping package `pdfescape' (already loaded). +Package: bigintcalc 2016/05/16 v1.4 Expandable calculations on big integers (HO +) +Package: bitset 2016/05/16 v1.2 Handle bit-vector datatype (HO) +Package: uniquecounter 2016/05/16 v1.3 Provide unlimited unique counter (HO) +) +Package hobsub Info: Skipping package `hobsub' (already loaded). +Package: letltxmacro 2016/05/16 v1.5 Let assignment for LaTeX macros (HO) +Package: hopatch 2016/05/16 v1.3 Wrapper for package hooks (HO) +Package: xcolor-patch 2016/05/16 xcolor patch +Package: atveryend 2016/05/16 v1.9 Hooks at the very end of document (HO) +Package hobsub Info: Skipping package `atbegshi' (already loaded). +Package hobsub Info: Skipping package `refcount' (already loaded). +Package: hycolor 2016/05/16 v1.8 Color options for hyperref/bookmark (HO) +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\auxhook +.sty" +Package: auxhook 2016/05/16 v1.4 Hooks for auxiliary files (HO) +) +\@linkdim=\dimen182 +\Hy@linkcounter=\count304 +\Hy@pagecounter=\count305 + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/hyperref\pd1enc. +def" +File: pd1enc.def 2018/11/30 v6.88e Hyperref: PDFDocEncoding definition (HO) +Now handling font encoding PD1 ... +... no UTF-8 mapping file for font encoding PD1 +) +\Hy@SavedSpaceFactor=\count306 + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/00miktex\hyperre +f.cfg" +File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive +) +Package hyperref Info: Hyper figures OFF on input line 4519. +Package hyperref Info: Link nesting OFF on input line 4524. +Package hyperref Info: Hyper index ON on input line 4527. +Package hyperref Info: Plain pages OFF on input line 4534. +Package hyperref Info: Backreferencing OFF on input line 4539. +Package hyperref Info: Implicit mode ON; LaTeX internals redefined. +Package hyperref Info: Bookmarks ON on input line 4772. +\c@Hy@tempcnt=\count307 +LaTeX Info: Redefining \url on input line 5125. +\XeTeXLinkMargin=\dimen183 +\Fld@menulength=\count308 +\Field@Width=\dimen184 +\Fld@charsize=\dimen185 +Package hyperref Info: Hyper figures OFF on input line 6380. +Package hyperref Info: Link nesting OFF on input line 6385. +Package hyperref Info: Hyper index ON on input line 6388. +Package hyperref Info: backreferencing OFF on input line 6395. +Package hyperref Info: Link coloring OFF on input line 6400. +Package hyperref Info: Link coloring with OCG OFF on input line 6405. +Package hyperref Info: PDF/A mode OFF on input line 6410. +LaTeX Info: Redefining \ref on input line 6450. +LaTeX Info: Redefining \pageref on input line 6454. +\Hy@abspage=\count309 +\c@Item=\count310 +\c@Hfootnote=\count311 +) +Package hyperref Info: Driver (autodetected): hpdftex. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/hyperref\hpdftex +.def" +File: hpdftex.def 2018/11/30 v6.88e Hyperref driver for pdfTeX +\Fld@listcount=\count312 +\c@bookmark@seq@number=\count313 + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\rerunfi +lecheck.sty" +Package: rerunfilecheck 2016/05/16 v1.8 Rerun checks for auxiliary files (HO) +Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2 +82. +) +\Hy@SectionHShift=\skip76 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\bkm-pdf +tex.def" +File: bkm-pdftex.def 2016/05/17 v1.26 bookmark driver for pdfTeX (HO) +\BKM@id=\count314 +)) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/currfile\currfil +e.sty" +Package: currfile 2015/04/23 v0.7c Provides the file path elements of the curre +nt input file + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/filehook\filehoo +k.sty" +Package: filehook 2011/10/12 v0.5d Hooks for input files + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/filehook\filehoo +k-scrlfile.sty" +Package: filehook-scrlfile 2011/01/03 v0.1 filehook patch for scrlfile package +Package filehook Info: Package 'scrlfile' detected and compensated for on input + line 102. +)) +\c@currfiledepth=\count315 +) + +Package hyperref Warning: Option `destlabel' has already been used, +(hyperref) setting the option has no effect on input line 141. + + +Package hyperref Warning: Option `pagebackref' has already been used, +(hyperref) setting the option has no effect on input line 141. + +Package hyperref Info: Option `bookmarksnumbered' set `true' on input line 141. + +Package hyperref Info: Option `colorlinks' set `true' on input line 141. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\transpa +rent.sty" +Package: transparent 2018/11/18 v1.3 Transparency via pdfTeX's color stack (HO) + +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/fancyhdr\fancyhd +r.sty" +Package: fancyhdr 2019/01/31 v3.10 Extensive control of page headers and footer +s +\f@nch@headwidth=\skip77 +\f@nch@O@elh=\skip78 +\f@nch@O@erh=\skip79 +\f@nch@O@olh=\skip80 +\f@nch@O@orh=\skip81 +\f@nch@O@elf=\skip82 +\f@nch@O@erf=\skip83 +\f@nch@O@olf=\skip84 +\f@nch@O@orf=\skip85 +) +\maxfoottitlewidth=\skip86 +\foottitlewidth=\skip87 +\c@n_sp_blocks=\count316 +\c@n_sp_items=\count317 + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\makeidx.sty +" +Package: makeidx 2014/09/29 v1.0m Standard LaTeX package +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/idxlayout\idxlay +out.sty" +Package: idxlayout 2012/03/30 v0.4d Configurable index layout + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tools\multicol.s +ty" +Package: multicol 2018/12/27 v1.8v multicolumn formatting (FMi) +\c@tracingmulticols=\count318 +\mult@box=\box70 +\multicol@leftmargin=\dimen186 +\c@unbalance=\count319 +\c@collectmore=\count320 +\doublecol@number=\count321 +\multicoltolerance=\count322 +\multicolpretolerance=\count323 +\full@width=\dimen187 +\page@free=\dimen188 +\premulticols=\dimen189 +\postmulticols=\dimen190 +\multicolsep=\skip88 +\multicolbaselineskip=\skip89 +\partial@page=\box71 +\last@line=\box72 +\maxbalancingoverflow=\dimen191 +\mult@rightbox=\box73 +\mult@grightbox=\box74 +\mult@gfirstbox=\box75 +\mult@firstbox=\box76 +\@tempa=\box77 +\@tempa=\box78 +\@tempa=\box79 +\@tempa=\box80 +\@tempa=\box81 +\@tempa=\box82 +\@tempa=\box83 +\@tempa=\box84 +\@tempa=\box85 +\@tempa=\box86 +\@tempa=\box87 +\@tempa=\box88 +\@tempa=\box89 +\@tempa=\box90 +\@tempa=\box91 +\@tempa=\box92 +\@tempa=\box93 +\c@columnbadness=\count324 +\c@finalcolumnbadness=\count325 +\last@try=\dimen192 +\multicolovershoot=\dimen193 +\multicolundershoot=\dimen194 +\mult@nat@firstbox=\box94 +\colbreak@box=\box95 +\mc@col@check@num=\count326 +) +\c@idxcols=\count327 +\indexcolsep=\skip90 +\indexrule=\skip91 +\ila@indentunit=\skip92 +\ila@initsep=\skip93 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/natbib\natbib.st +y" +Package: natbib 2010/09/13 8.31b (PWD, AO) +\bibhang=\skip94 +\bibsep=\skip95 +LaTeX Info: Redefining \cite on input line 694. +\c@NAT@ctr=\count328 +) +runsystem(makeindex -q Kratos_Verification.nlo -s deltares_nomentbl.ist -o Krat +os_Verification.nls)...executed (allowed). + +\@nomenclaturefile=\write4 +\openout4 = `Kratos_Verification.nlo'. + +Package nomencl Info: Writing nomenclature file Kratos_Verification.nlo on inpu +t line 1877. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/enumitem\enumite +m.sty" +Package: enumitem 2019/02/04 v3.8 Customized lists +\labelindent=\skip96 +\enit@outerparindent=\dimen195 +\enit@toks=\toks37 +\enit@inbox=\box96 +\enit@count@id=\count329 +\enitdp@description=\count330 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/xcolor\xcolor.st +y" +Package: xcolor 2016/05/11 v2.12 LaTeX color extensions (UK) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics-cfg\col +or.cfg" +File: color.cfg 2016/01/02 v1.6 sample color configuration +) +Package xcolor Info: Driver file: pdftex.def on input line 225. +LaTeX Info: Redefining \color on input line 709. +Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1348. +Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1352. +Package xcolor Info: Model `RGB' extended on input line 1364. +Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1366. +Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1367. +Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1368. +Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1369. +Package xcolor Info: Model `Gray' substituted by `gray' on input line 1370. +Package xcolor Info: Model `wave' substituted by `hsb' on input line 1371. +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tabulary\tabular +y.sty" +Package: tabulary 2014/06/11 v0.10 tabulary package (DPC) +\TY@count=\count331 +\TY@linewidth=\dimen196 +\tymin=\dimen197 +\tymax=\dimen198 +\TY@tablewidth=\dimen199 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/placeins\placein +s.sty" +Package: placeins 2005/04/18 v 2.2 +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/ms\ragged2e.sty" +Package: ragged2e 2009/05/21 v2.1 ragged2e Package (MS) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/ms\everysel.sty" +Package: everysel 2011/10/28 v1.2 EverySelectfont Package (MS) +) +\CenteringLeftskip=\skip97 +\RaggedLeftLeftskip=\skip98 +\RaggedRightLeftskip=\skip99 +\CenteringRightskip=\skip100 +\RaggedLeftRightskip=\skip101 +\RaggedRightRightskip=\skip102 +\CenteringParfillskip=\skip103 +\RaggedLeftParfillskip=\skip104 +\RaggedRightParfillskip=\skip105 +\JustifyingParfillskip=\skip106 +\CenteringParindent=\skip107 +\RaggedLeftParindent=\skip108 +\RaggedRightParindent=\skip109 +\JustifyingParindent=\skip110 +) (Kratos_Verification.aux + +LaTeX Warning: Label `fig:was:used:in:doc' multiply defined. + + +LaTeX Warning: Label `table:was:used:in:doc' multiply defined. + + +LaTeX Warning: Label `fig:was:used:in:doc' multiply defined. + + +LaTeX Warning: Label `table:was:used:in:doc' multiply defined. + + +LaTeX Warning: Label `fig:was:used:in:doc' multiply defined. + + +LaTeX Warning: Label `table:was:used:in:doc' multiply defined. + + +LaTeX Warning: Label `fig:was:used:in:doc' multiply defined. + + +LaTeX Warning: Label `fig:was:used:in:doc' multiply defined. + +) +\openout1 = `Kratos_Verification.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 43. +LaTeX Font Info: ... okay on input line 43. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 43. +LaTeX Font Info: ... okay on input line 43. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 43. +LaTeX Font Info: ... okay on input line 43. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 43. +LaTeX Font Info: ... okay on input line 43. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 43. +LaTeX Font Info: ... okay on input line 43. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 43. +LaTeX Font Info: ... okay on input line 43. +LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 43. +LaTeX Font Info: Try loading font information for TS1+cmr on input line 43. + ("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\ts1cmr.fd" +File: ts1cmr.fd 2014/09/29 v2.5h Standard LaTeX font definitions +) +LaTeX Font Info: ... okay on input line 43. +LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 43. +LaTeX Font Info: ... okay on input line 43. +LaTeX Font Info: Try loading font information for T1+phv on input line 43. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/psnfss\t1phv.fd" +File: t1phv.fd 2001/06/04 scalable font definitions for T1/phv. +) +LaTeX Font Info: Font shape `T1/phv/m/n' will be +(Font) scaled to size 10.07397pt on input line 43. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/context/base\supp-pdf. +mkii" +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count332 +\scratchdimen=\dimen256 +\scratchbox=\box97 +\nofMPsegments=\count333 +\nofMParguments=\count334 +\everyMPshowfont=\toks38 +\MPscratchCnt=\count335 +\MPscratchDim=\dimen257 +\MPnumerator=\count336 +\makeMPintoPDFobject=\count337 +\everyMPtoPDFconversion=\toks39 +) +\AtBeginShipoutBox=\box98 + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\pdflsca +pe.sty" +Package: pdflscape 2016/05/14 v0.11 Display of landscape pages in PDF (HO) + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics\lscape. +sty" +Package: lscape 2000/10/22 v3.01 Landscape Pages (DPC) +) +Package pdflscape Info: Auto-detected driver: pdftex on input line 81. +) +Package caption Info: Begin \AtBeginDocument code. +Package caption Info: hyperref package is loaded. +Package caption Info: rotating package is loaded. +Package caption Info: End \AtBeginDocument code. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/translator\trans +lator-basic-dictionary-English.dict" +Dictionary: translator-basic-dictionary, Language: English +) +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/siunitx\siunitx- +abbreviations.cfg" +File: siunitx-abbreviations.cfg 2017/11/26 v2.7k siunitx: Abbreviated units +) +Package lastpage Info: Please have a look at the pageslts package at +(lastpage) https://www.ctan.org/pkg/pageslts +(lastpage) ! on input line 43. +Package hyperref Info: Link coloring ON on input line 43. +LaTeX Info: Redefining \ref on input line 43. +LaTeX Info: Redefining \pageref on input line 43. +LaTeX Info: Redefining \nameref on input line 43. + ABD: EverySelectfont initializing macros +LaTeX Info: Redefining \selectfont on input line 43. +LaTeX Font Info: Try loading font information for U+msa on input line 43. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsfonts\umsa.fd +" +File: umsa.fd 2013/01/14 v3.01 AMS symbols A +) +LaTeX Font Info: Try loading font information for U+msb on input line 43. + +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/amsfonts\umsb.fd +" +File: umsb.fd 2013/01/14 v3.01 AMS symbols B +) +LaTeX Font Info: Font shape `T1/phv/m/n' will be +(Font) scaled to size 15.89755pt on input line 53. +LaTeX Font Info: Font shape `T1/phv/bx/n' in size <17.28> not available +(Font) Font shape `T1/phv/b/n' tried instead on input line 53. +LaTeX Font Info: Font shape `T1/phv/b/n' will be +(Font) scaled to size 15.89755pt on input line 53. +LaTeX Font Info: Font shape `T1/phv/m/n' will be +(Font) scaled to size 27.47115pt on input line 53. +LaTeX Font Info: Font shape `T1/phv/bx/n' in size <29.86> not available +(Font) Font shape `T1/phv/b/n' tried instead on input line 53. +LaTeX Font Info: Font shape `T1/phv/b/n' will be +(Font) scaled to size 27.47115pt on input line 53. +LaTeX Font Info: Font shape `T1/phv/bx/sc' in size <29.86> not available +(Font) Font shape `T1/phv/b/sc' tried instead on input line 53. +LaTeX Font Info: Font shape `T1/phv/b/sc' will be +(Font) scaled to size 27.47115pt on input line 53. +LaTeX Font Info: Font shape `T1/phv/m/n' will be +(Font) scaled to size 13.24796pt on input line 53. +LaTeX Font Info: Font shape `T1/phv/bx/n' in size <14.4> not available +(Font) Font shape `T1/phv/b/n' tried instead on input line 53. +LaTeX Font Info: Font shape `T1/phv/b/n' will be +(Font) scaled to size 13.24796pt on input line 53. + [1 + + +{C:/Users/noordam/AppData/Local/MiKTeX/2.9/pdftex/config/pdftex.map}] +LaTeX Font Info: Font shape `T1/phv/bx/n' in size <10.95> not available +(Font) Font shape `T1/phv/b/n' tried instead on input line 53. +LaTeX Font Info: Font shape `T1/phv/b/n' will be +(Font) scaled to size 10.07397pt on input line 53. +LaTeX Font Info: Font shape `T1/phv/bx/sc' in size <10.95> not available +(Font) Font shape `T1/phv/b/sc' tried instead on input line 53. +LaTeX Font Info: Font shape `T1/phv/b/sc' will be +(Font) scaled to size 10.07397pt on input line 53. + +Overfull \hbox (18.0pt too wide) in paragraph at lines 53--53 +[][] + [] + + +Overfull \hbox (18.0pt too wide) in paragraph at lines 53--53 +[][] + [] + +LaTeX Font Info: Try loading font information for TS1+phv on input line 53. +("C:\Users\noordam\AppData\Local\Programs\MiKTeX 2.9\tex/latex/psnfss\ts1phv.fd +" +File: ts1phv.fd 2001/06/04 scalable font definitions for TS1/phv. +) +LaTeX Font Info: Font shape `TS1/phv/m/n' will be +(Font) scaled to size 10.07397pt on input line 53. + [2 + +] (Kratos_Verification.toc + +Package xcolor Warning: Incompatible color definition on input line 2. + + +Package xcolor Warning: Incompatible color definition on input line 3. + + +Package xcolor Warning: Incompatible color definition on input line 4. + + +Package xcolor Warning: Incompatible color definition on input line 5. + + +Package xcolor Warning: Incompatible color definition on input line 6. + + +Package xcolor Warning: Incompatible color definition on input line 7. + + +Package xcolor Warning: Incompatible color definition on input line 8. + + +Package xcolor Warning: Incompatible color definition on input line 9. + + +Package xcolor Warning: Incompatible color definition on input line 10. + + +Package xcolor Warning: Incompatible color definition on input line 11. + + +Package xcolor Warning: Incompatible color definition on input line 12. + + +Package xcolor Warning: Incompatible color definition on input line 13. + + +Package xcolor Warning: Incompatible color definition on input line 14. + + +Package xcolor Warning: Incompatible color definition on input line 15. + + +Package xcolor Warning: Incompatible color definition on input line 16. + + +Package xcolor Warning: Incompatible color definition on input line 17. + + +Package xcolor Warning: Incompatible color definition on input line 18. + + +Package xcolor Warning: Incompatible color definition on input line 19. + + +Package xcolor Warning: Incompatible color definition on input line 20. + + +Package xcolor Warning: Incompatible color definition on input line 21. + + +Package xcolor Warning: Incompatible color definition on input line 22. + + +Package xcolor Warning: Incompatible color definition on input line 23. + + +Package xcolor Warning: Incompatible color definition on input line 24. + + +Package xcolor Warning: Incompatible color definition on input line 25. + + +Package xcolor Warning: Incompatible color definition on input line 26. + + +Package xcolor Warning: Incompatible color definition on input line 27. + + +Package xcolor Warning: Incompatible color definition on input line 28. + + +Package xcolor Warning: Incompatible color definition on input line 29. + + +Package xcolor Warning: Incompatible color definition on input line 30. + +) +\tf@toc=\write5 +\openout5 = `Kratos_Verification.toc'. + + [3 + + +] +LaTeX Font Info: Font shape `T1/phv/m/sc' will be +(Font) scaled to size 10.07397pt on input line 53. + [4 + +] (Kratos_Verification.lof + +Package xcolor Warning: Incompatible color definition on input line 4. + + +Package xcolor Warning: Incompatible color definition on input line 6. + + +Package xcolor Warning: Incompatible color definition on input line 7. + + +Package xcolor Warning: Incompatible color definition on input line 9. + + +Package xcolor Warning: Incompatible color definition on input line 10. + + +Package xcolor Warning: Incompatible color definition on input line 12. + +) +\tf@lof=\write6 +\openout6 = `Kratos_Verification.lof'. + + [5] [6 + +] (Kratos_Verification.lot + +Package xcolor Warning: Incompatible color definition on input line 4. + + +Package xcolor Warning: Incompatible color definition on input line 5. + + +Package xcolor Warning: Incompatible color definition on input line 6. + + +Package xcolor Warning: Incompatible color definition on input line 8. + + +Package xcolor Warning: Incompatible color definition on input line 9. + + +Package xcolor Warning: Incompatible color definition on input line 10. + + +Package xcolor Warning: Incompatible color definition on input line 11. + + +Package xcolor Warning: Incompatible color definition on input line 13. + +) +\tf@lot=\write7 +\openout7 = `Kratos_Verification.lot'. + + (Kratos_Verification.nls) [7] [8 + +] +Chapter 1. + +Overfull \hbox (7.64561pt too wide) in paragraph at lines 56--58 +\T1/phv/m/n/10.95 achieve this dif-fer-ent bench-marks are cre-ated to test dif +-fer-ent parts of the Kratos-Geomechanics + [] + +[1 + +] [2 + +] +Chapter 2. +LaTeX Font Info: Font shape `T1/phv/m/it' in size <10.95> not available +(Font) Font shape `T1/phv/m/sl' tried instead on input line 64. +LaTeX Font Info: Font shape `T1/phv/m/sl' will be +(Font) scaled to size 10.07397pt on input line 64. + +Package xcolor Warning: Incompatible color definition on input line 65. + +LaTeX Font Info: Font shape `T1/phv/m/n' will be +(Font) scaled to size 9.19998pt on input line 68. +LaTeX Font Info: Font shape `T1/phv/m/sl' will be +(Font) scaled to size 9.19998pt on input line 68. +LaTeX Font Info: Font shape `T1/phv/bx/sl' in size <10> not available +(Font) Font shape `T1/phv/b/sl' tried instead on input line 68. +LaTeX Font Info: Font shape `T1/phv/b/sl' will be +(Font) scaled to size 9.19998pt on input line 68. + +Package xcolor Warning: Incompatible color definition on input line 90. + + +Package xcolor Warning: Incompatible color definition on input line 108. + + +Package caption Warning: \label without proper reference on input line 112. +See the caption package documentation for explanation. + + +LaTeX Warning: Reference `fig:material_bm_1' on page 3 undefined on input line +108. + + +File: figures/material_bm_1.png Graphic file (type png) + +Package pdftex.def Info: figures/material_bm_1.png used on input line 111. +(pdftex.def) Requested size: 206.28249pt x 226.20148pt. +[3] + +Package xcolor Warning: Incompatible color definition on input line 124. + + +Package xcolor Warning: Incompatible color definition on input line 124. + + +Package xcolor Warning: Incompatible color definition on input line 134. + +[4 <./figures/material_bm_1.png>] [5] [6 + +] +Chapter 3. + +Package xcolor Warning: Incompatible color definition on input line 157. + + +Package xcolor Warning: Incompatible color definition on input line 179. + + +File: figures/beam_bm_2_1.png Graphic file (type png) + +Package pdftex.def Info: figures/beam_bm_2_1.png used on input line 183. +(pdftex.def) Requested size: 206.28249pt x 173.56339pt. + +Package xcolor Warning: Incompatible color definition on input line 191. + +[7 <./figures/beam_bm_2_1.png>] + +Package xcolor Warning: Incompatible color definition on input line 198. + + +Package xcolor Warning: Incompatible color definition on input line 215. + + +Package xcolor Warning: Incompatible color definition on input line 236. + + +File: figures/beam_bm_2_2.png Graphic file (type png) + +Package pdftex.def Info: figures/beam_bm_2_2.png used on input line 240. +(pdftex.def) Requested size: 206.28249pt x 173.56339pt. + +LaTeX Warning: `h' float specifier changed to `ht'. + + +Package xcolor Warning: Incompatible color definition on input line 248. + + +Package xcolor Warning: Incompatible color definition on input line 254. + +[8] [9 <./figures/beam_bm_2_2.png>] [10 + +] +Chapter 4. + +Package xcolor Warning: Incompatible color definition on input line 279. + + +File: figures/mesh_rigid_footing_elastic_soil.png Graphic file (type png) + +Package pdftex.def Info: figures/mesh_rigid_footing_elastic_soil.png used on i +nput line 283. +(pdftex.def) Requested size: 206.28249pt x 127.0408pt. + +Package xcolor Warning: Incompatible color definition on input line 323. + + +File: figures/vertical_stress_rigid_footing_elastic_soil.png Graphic file (type + png) + +Package pdftex.def Info: figures/vertical_stress_rigid_footing_elastic_soil.png + used on input line 327. +(pdftex.def) Requested size: 206.28249pt x 154.07028pt. + +LaTeX Warning: `h' float specifier changed to `ht'. + +[11 <./figures/mesh_rigid_footing_elastic_soil.png>] [12 <./figures/vertical_st +ress_rigid_footing_elastic_soil.png>] +Chapter 5. + +Overfull \hbox (2.19734pt too wide) in paragraph at lines 334--335 +\T1/phv/m/n/10.95 In this bench-mark 1D con-sol-i-da-tion is tested on lin-ear +elas-tic soil, us-ing Kratos-Geomechanics. + [] + + +File: figures/1d_consolidation_result.png Graphic file (type png) + +Package pdftex.def Info: figures/1d_consolidation_result.png used on input lin +e 359. +(pdftex.def) Requested size: 206.28249pt x 154.07028pt. +[13 + + <./figures/1d_consolidation_result.png>] [14 + +] (Kratos_Verification.bbl + +Package natbib Warning: Empty `thebibliography' environment on input line 8. + +) +AED: lastpage setting LastPage +[15] +Package atveryend Info: Empty hook `BeforeClearDocument' on input line 379. +Package atveryend Info: Empty hook `AfterLastShipout' on input line 379. + (Kratos_Verification.aux) +Package atveryend Info: Executing hook `AtVeryEndDocument' on input line 379. +Package atveryend Info: Empty hook `AtEndAfterFileList' on input line 379. + + +LaTeX Warning: There were undefined references. + + +LaTeX Warning: There were multiply-defined labels. + + ) +Here is how much of TeX's memory you used: + 26164 strings out of 492946 + 477672 string characters out of 3125378 + 587254 words of memory out of 3000000 + 29563 multiletter control sequences out of 15000+200000 + 586407 words of font info for 85 fonts, out of 3000000 for 9000 + 1143 hyphenation exceptions out of 8191 + 55i,12n,77p,828b,764s stack positions out of 5000i,500n,10000p,200000b,50000s +{C:/Users/noordam/AppData/Local/Programs/MiKTeX 2.9/fonts/enc/dvips/base/8r.e +nc} +Output written on Kratos_Verification.pdf (23 pages, 309513 bytes). +PDF statistics: + 378 PDF objects out of 1000 (max. 8388607) + 74 named destinations out of 1000 (max. 500000) + 263 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.lot b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.lot new file mode 100644 index 000000000000..33976c390f34 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.lot @@ -0,0 +1,14 @@ +\babel@toc {english}{} +\addvspace {10\p@ } +\addvspace {10\p@ } +\contentsline {table}{\numberline {2.1}{\ignorespaces Coordinates of square specimen\relax }}{3}{table.caption.4}% +\contentsline {table}{\numberline {2.2}{\ignorespaces Line Load inputs for benchmark 1\relax }}{3}{table.caption.5}% +\contentsline {table}{\numberline {2.3}{\ignorespaces Results of displacements for benchmark1 \relax }}{4}{table.caption.7}% +\addvspace {10\p@ } +\contentsline {table}{\numberline {3.1}{\ignorespaces Coordinates plate element\relax }}{7}{table.caption.8}% +\contentsline {table}{\numberline {3.2}{\ignorespaces Results of deflection for benchmark 2 with the application of point load \relax }}{8}{table.caption.10}% +\contentsline {table}{\numberline {3.3}{\ignorespaces Coordinates plate element\relax }}{8}{table.caption.11}% +\contentsline {table}{\numberline {3.4}{\ignorespaces Results of deflection for benchmark 2 with the application of line load \relax }}{9}{table.caption.13}% +\addvspace {10\p@ } +\contentsline {table}{\numberline {4.1}{\ignorespaces Results of reaction force for benchmark 3 with the application of a settlement \relax }}{11}{table.caption.15}% +\addvspace {10\p@ } diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.nlo b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.nlo new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.nls b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.nls new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tcp b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tcp new file mode 100644 index 000000000000..9fae45b53b43 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tcp @@ -0,0 +1,12 @@ +[FormatInfo] +Type=TeXnicCenterProjectInformation +Version=4 + +[ProjectInfo] +MainFile=Kratos_Verification.tex +UseBibTeX=1 +UseMakeIndex=1 +ActiveProfile=LaTeX ⇨ PDF +ProjectLanguage=en +ProjectDialect=US + diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tex b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tex new file mode 100644 index 000000000000..8967093bfebc --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tex @@ -0,0 +1,379 @@ +\documentclass{deltares_manual_style} +\usepackage{enumitem} +\usepackage{amssymb,amsmath} +\usepackage{xcolor,colortbl,color} +\usepackage{tabularx} +\usepackage{tabulary} +\usepackage{hyperref} +\usepackage{float} +\usepackage{placeins} +%------------------------------------------------------------------------------ +\hypersetup +{ + pdfauthor = {Deltares}, + pdftitle = {Kratos Geomechanics Application}, + pdfkeywords = {Deltares, User Manual}, + pdfcreator = {LaTeX hyperref}, + pdfproducer = {ps2pdf} +} +%------------------------------------------------------------------------------ +% +\renewcommand\BackgroundPicPart{ + \put(0,0){ + \parbox[b][\paperheight]{\paperwidth}{% + \vspace{8\baselineskip} + \hspace{44mm} % 20mm wegens leftmarginskip + 24 mm ~ 1 inch +% \includegraphics[width=\paperwidth, height=\paperheight, keepaspectratio]{pictures/dsheetpiling-part.png}% + \vfill + } + } +} +% Todo add a ribbon? +%\renewcommand\BackgroundPicChapter{ +% \put(0,0){ +% \parbox[b][\paperheight]{\paperwidth}{% +% \vspace{4\baselineskip} +% \hspace{220mm} +% \includegraphics[width=15mm]{pictures/ribbon.jpg}% +% \vfill +% } +% } +%} + +\begin{document} +% TODO insert pdf cover +% \pagestyle{empty} +%\includepdf[pages=1,offset=72 -70]{pictures/cover_user_manual.pdf} % First and last page +%\cleardoublepage + +\title{\textsc{Kratos Geomechanics}} +\subtitle{Finite element model} +\manualtype{Verification Report} +\version{0.1} +\manualtitle + +\chapter{Introduction}\label{intro} +This document contains verification examples for the Kratos-Geomechanics application. To achieve this different benchmarks +are created to test different parts of the Kratos-Geomechanics application. + +\chapter{Benchmark 1: Bi-axial shearing test with linear elastic model} \label{chap:bench1} +In this benchmark Bia-axial shearing test conditions are tested in the Kratos-Geomechanics application. In that way, +this example can be used to verify elastic deformation with a linear elastic model. + +\section{Geometry and boundary conditions} +The geometry created in Kratos is a 2-D square specimen ($1\times1m^{2}$). To create the geometry click on the \textit{Create line} +button and enter the points as they are described in \autoref{tab:CoordinatesOfSquareSpeciment}. After creating the square specimen +a surface needs to be created so that the soil elements can be assigned to it. This can be done by clicking the \textit{create NURBS surface} and then the surface of the square specimen created. +\begin{table*}[h] + \caption{Coordinates of square specimen} + \label{tab:CoordinatesOfSquareSpeciment} + \centering + \begin{tabular}{|c|c|} + \hline + x-coordinate & y-coordinate \\ \hline + 0 & 0 \\ \hline + 0 & 1 \\ \hline + 1 & 1 \\ \hline + 1 & 0 \\ \hline + 0 & 0 \\ \hline + \end{tabular} +\end{table*} + +For the boundary conditions the following constrains are applied to the model: +\begin{itemize} + \item a \textit{Solid Displacement} is used to fix the bottom boundary in the y direction. By setting the \textit{SOLID DISPLACEMENT Y} to <0.0>. + \item a \textit{Solid Displacement} is used to fix the bottom left corner in the x and the y direction. By setting + the \textit{SOLID DISPLACEMENT Y} and the \textit{SOLID DISPLACEMENT X} to <0.0>. +\end{itemize} + +The loads applied to the geometry are line load in this case and they are applied to the edges of the geometry. This is done by +selecting the \textit{Loads} menu and inputting the loads that are shown in \autoref{tab:loadinputbench1}. +\begin{table*}[h] + \caption{Line Load inputs for benchmark 1} + \label{tab:loadinputbench1} + \centering + \begin{tabular}{|c|c|c|c|c|} + \hline + Direction & Assigned Line & Assigned Line & Value & Unit \\ + Setting & Coordinate x & Coordinate y & & \\ \hline + LINE LOAD X & [0,1] & [1,1] & -1 & N/m \\ \hline + LINE LOAD X & [0,0] & [1,0] & +1 & N/m \\ \hline + LINE LOAD Y & [0,0] & [0,1] & -1 & N/m\\ \hline + LINE LOAD Y & [1,1] & [0,1] & +1 & N/m \\ \hline + \end{tabular} +\end{table*} + +\section{Material} +The material selected for this benchmark is a linear elastic drained soil material. The inputs of this can be seen in +\autoref{fig:material_bm_1} and can be set on the \textit{Elements} menu item. +\begin{figure}[H] + \centering + \includegraphics[width=0.5\textwidth]{figures/material_bm_1.png} + \label{fig:material_bm_1} + \caption{Material input of benchmark 1} +\end{figure} + +\section{Mesh Generation} +The mesh in this case should be generated coarsely. In this case only two elements will be produced. To produce the mesh +click on \textit{Mesh} menu and then from the drop down list select \textit{Generate mesh} and enter for \textit{Enter +size of elements to be generated} <1>. +\section{Results} + The Kratos-Geomechanics application uses as output strain tensor the \textit{Green-Langrange-Strain-Tensor}. The output of the calculation in this case is $\epsilon_{xy} = 1.25\times10^{-3}$ which is half of shear strain $\tau$. +Therefore, the shear strain is $\tau= 2.5\times10^{-3}$. + +The analytical solution can be calculated as follows from \autoref{eq:shearmoduluscalc} and \autoref{eq:shearstraincalc}. +\begin{equation} \label{eq:shearmoduluscalc} +G = \frac{E}{1( 1 + \nu')} = 400 kN/m^{2} +\end{equation} + +\begin{equation}\label{eq:shearstraincalc} +\tau = \frac{\gamma}{G} = 2.5\times10^-{3} for \tau=1 kN/m +\end{equation} + +The comparison of the displacements calculated by Kratos can be compared with the results of the analytical solution in +\autoref{tab:Resultsbm1}. + +\begin{table}[H] + \caption{Results of displacements for benchmark1 } + \label{tab:Resultsbm1} + \centering + \begin{tabular}{|c|c|c|} + \hline + Kratos & Benchmark & Error[\%] \\ \hline + $2.50\times10^{-3}$ & $2.50\times10^{-3}$ & $0.00$ \\ \hline + \end{tabular} +\end{table} + +To run this benchmark run file smoothrigidfootingonelasticsoil.gid. + +\chapter{Benchmark 2: Bending of plates} \label{Bench2} +In this benchmark the bending of plate elements with Kratos-Geomechanics will be tested. Two different plate elements of +unit length are tested. In the first case a point load is applied on the first plate and the second case +a line load is applied in the second plate. The plates are modeled in 2D geometry thus the material used to model the +plates are beam elements. +\section{Bending of plate when point load is applied} +\subsection{Geometry} +In this case a line of 1m needs to be created. To create the line click on the \textit{Create line} button and enter the +points that are part of \autoref{tab:platebend2.1}. +\begin{table*}[h] + \caption{Coordinates plate element} + \label{tab:platebend2.1} + \centering + \begin{tabular}{|c|c|} + \hline + x-coordinate & y-coordinate \\ \hline + 0 & 0 \\ \hline + 0.5 & 0 \\ \hline + 1 & 0 \\ \hline + \end{tabular} +\end{table*} + +The beam is simply-supported so solid displacements are used to model the fixities at the points. For points <0,0> and +<1,0> a \textit{Solid Displacement} of <0.0> is applied for x and y direction. + +The point load is applied on point <0.5,0> from the menu item \textit{Loads}. By selecting \textit{Point Load} and +setting \textit{POINT LOAD Y} to <100N> the load can be defined. + +\subsection{Material} +The material of the plate element can be defined by selecting the menu item \textit{Elements} and then filling out the +values of \autoref{fig:beam_bm_2.1}. + +\begin{figure}[h] + \centering + \includegraphics[width=0.50\textwidth]{figures/beam_bm_2_1.png} + \caption{Beam element of benchmark 2} + \label{fig:beam_bm_2.1} +\end{figure} + +\subsection{Results} +% ToDo : when issue #7 is done add the part about bending moments and shear stresses. +In this benchmark the result of the maximum deflection is compared with the analytical result. The analytical +calculation of simply supported beam with point load at the center is described in \autoref{eq:disp2.1}. In this case $F = 100kN$ , +$l = 1m$ and $EI = 83.33 kNm^{2}/m$. + +\begin{equation}\label{eq:disp2.1} +u_{max} = \frac{1}{48} \frac{F l^{3}}{EI} = 25.00mm +\end{equation} + +After performing the calculation in Kratos-Geomechanics the results are compared with the benchmark in \autoref{tab:Resultsbm2.1} + +\begin{table}[H] + \caption{Results of deflection for benchmark 2 with the application of point load } + \label{tab:Resultsbm2.1} + \centering + \begin{tabular}{|c|c|c|} + \hline + Kratos & Benchmark & Error\\ \hline + [mm] & [mm] & [\%] \\ \hline + $25.01$ & $25.00$ & $0.04$ \\ \hline + \end{tabular} +\end{table} + +\section{Bending of plate when line load is applied} +\subsection{Geometry} +In this case a line of 1m needs to be created. To create the line click on the \textit{Create line} button and enter the +points that are part of \autoref{tab:platebend2.2}. +\begin{table*}[h] + \caption{Coordinates plate element} + \label{tab:platebend2.2} + \centering + \begin{tabular}{|c|c|} + \hline + x-coordinate & y-coordinate \\ \hline + 0 & 0 \\ \hline + 1 & 0 \\ \hline + \end{tabular} +\end{table*} + +The beam is simply-supported so solid displacements are used to model the fixities at the points. For points <0,0> and +<1,0> a \textit{Solid Displacement} of <0.0> is applied for x and y direction. + +The line load is applied on the full length of the beam from the menu item \textit{Loads}. By selecting \textit{Line Load} and +setting \textit{POINT LOAD Y} to <200N/m> the load can be defined. + +\subsection{Material} +The material of the plate element can be defined by selecting the menu item \textit{Elements} and then filling out the +values of \autoref{fig:beam_bm_2.2}. + +\begin{figure}[h] + \centering + \includegraphics[width=0.50\textwidth]{figures/beam_bm_2_2.png} + \caption{Beam element of benchmark 2} + \label{fig:beam_bm_2.2} +\end{figure} + +\subsection{Results} +% ToDo : when issue #7 is done add the part about bending moments and shear stresses. +In this benchmark the result of the maximum deflection is compared with the analytical result. The analytical +calculation of simply supported beam with line load at the center is described in \autoref{eq:disp2.2}. In this case $q = 100kN/m$ , $l = 1m$ and $EI = 83.33 kNm^{2}/m$. + +\begin{equation}\label{eq:disp2.2} +u_{max} = \frac{5}{ 384} \frac{q l^{4}}{EI} = 31.25mm +\end{equation} + +After performing the calculation in Kratos-Geomechanics the results are compared with the benchmark in \autoref{tab:Resultsbm2.2} + +\begin{table}[H] + \caption{Results of deflection for benchmark 2 with the application of line load } + \label{tab:Resultsbm2.2} + \centering + \begin{tabular}{|c|c|c|} + \hline + Kratos & Benchmark & Error\\ \hline + [mm] & [mm] & [\%] \\ \hline + $31.25$ & $31.25$ & $0.00$ \\ \hline + \end{tabular} +\end{table} + +To run this benchmark run file Kratos\_line\_load.gid and bendingofplatepointload.gid. + + + +\chapter{Benchmark 3: Smooth rigid footing on elastic soil} +In this benchmark a smooth rigid footing is tested on elastic soil with Kratos-Geomechanics. + +\section{Geometry} + +A uniform displacement of 0.01 m is applied + +The geometry and mesh is shown in \autoref{fig:rigid_footing__geometry_bm_3} + +\begin{figure}[h] + \centering + \includegraphics[width=0.50\textwidth]{figures/mesh_rigid_footing_elastic_soil.png} + \caption{Geometry and mesh of model} + \label{fig:rigid_footing__geometry_bm_3} +\end{figure} + +\section{Material} + +In this benchmark, the soil is modelled with linear elastic drained elements. The applied Youngs Modulus, $E = 1333 \space kN/m^{2}$; the applied Poisson ratio, $nu' = 0.333$. + + + + +\section{Meshing} + +The mesh is generated using 6-node triangular elements. Along the footing, a mesh size is chosen of 0.015 m, within the rest of the geometry, a mesh size of 0.2 m is chosen. + +\section{Results} + + +\begin{equation}\label{eq:reaction_force_analytical} +F = \frac{2u(1+\nu')G}{\delta} = 15.15 +%u = \frac{F\delta}{2(1+\nu')G} +\end{equation} + +Since the problem is symmetric, the reaction force to compare is half the analytically calculated reaction force, i.e. $F=7.57$. + + +\begin{table}[H] + \caption{Results of reaction force for benchmark 3 with the application of a settlement } + \label{tab:Resultsbm3} + \centering + \begin{tabular}{|c|c|c|c|} + \hline + Kratos & Plaxis 2D &Benchmark & Error\\ \hline + [mm] & [mm] & [mm] & [\%] \\ \hline + $7.39$ & $7.36$ & $7.57$ & $2.43$ \\ \hline + \end{tabular} +\end{table} + + +In \autoref{fig:rigid_footing_bm_3} it is shown how the vertical stress develops underneath the rigid footing, results are shown following a Plaxis calculation, a Kratos-Geomechanics calculation and an analytical calculation. The results following the Plaxis calculation and the Kratos-Geomechanics calculation are effectively equal, both these results are in good accordance with the analytical results. + +\begin{figure}[h] + \centering + \includegraphics[width=0.50\textwidth]{figures/vertical_stress_rigid_footing_elastic_soil.png} + \caption{Vertical stress underneath rigid footing benchmark 3} + \label{fig:rigid_footing_bm_3} +\end{figure} + + +\chapter{Benchmark 4: 1D consolidation on elastic soil} +In this benchmark 1D consolidation is tested on linear elastic soil, using Kratos-Geomechanics. This benchmark includes multiple stages and a time dependent calculation. + +\section{Geometry} + +This benchmark is tested on a soil profile with a height of 1.0 m and a width of 0.1 m. See figure @@. The side and bottom boundaries are impermeable. At the top boundary, a 0 pore pressure condition and a line-load of 1kN/m are applied. + +@@ add figure @@ + +\section{Materials} +The soil is modelled with linear elastic undrained elements. The applied Youngs modulus, $E=1000\space kN/m^{2}$; the applied Poisson's ratio, $\nu'=0.0$ and the applied permeability in x- and y-direction, $k=0.001 \space m/day$. + +\section{Meshing} +The mesh is generated using 6-node triangular elements with a size of 0.05 m. + + + + +\section{Calculation} + +The first phase is calculated as \textit{Soil undrained}, the following phases are calculated as \textit{Soil two phase}. All phases are calculated using the Quasi-Static solution type. The 0 pore pressure boundary condition is activated from phase 2 and onwards. In total, 11 phases are calculated at: [0.0 0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0] days. + + + +\begin{figure}[h] + \centering + \includegraphics[width=0.50\textwidth]{figures/1d_consolidation_result.png} + \caption{Relative excess pore pressure versus relative height on different time steps} + \label{fig:1d_consolidation_bm_4} +\end{figure} + + +\section{Results} +Relative excess pore pressure can be determined analytically as a function of time and depth, as shown in the following formula [@@ref@@]. + +\begin{equation}\label{eq:relative_excess_pore_pressure_analytical} +\frac{p}{p_{0}} = \frac{3}{\pi}\sum_{j=1}^{\inf}\frac{(-1)^{j-1}}{2j-1}\cos[(2j-1)\frac{\pi}{2}\frac{y}{h}]\exp[-(2j-1)^{2}\frac{\pi^{2}}{4}\frac{c_{v}t}{h^{2}}] +%u = \frac{F\delta}{2(1+\nu')G} +\end{equation} + + + + + +\nonumchapter{Bibliography} +\bibliography{references/kratos_references} +\end{document} diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.toc b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.toc new file mode 100644 index 000000000000..e4b02ba49e2c --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.toc @@ -0,0 +1,30 @@ +\babel@toc {english}{} +\contentsline {chapter}{List of Figures}{v}{chapter*.2}% +\contentsline {chapter}{List of Tables}{vii}{chapter*.3}% +\contentsline {chapter}{\numberline {1}Introduction}{1}{chapter.1}% +\contentsline {chapter}{\numberline {2}Benchmark 1: Bi-axial shearing test with linear elastic model}{3}{chapter.2}% +\contentsline {section}{\numberline {2.1}Geometry and boundary conditions}{3}{section.2.1}% +\contentsline {section}{\numberline {2.2}Material}{4}{section.2.2}% +\contentsline {section}{\numberline {2.3}Mesh Generation}{4}{section.2.3}% +\contentsline {section}{\numberline {2.4}Results}{4}{section.2.4}% +\contentsline {chapter}{\numberline {3}Benchmark 2: Bending of plates}{7}{chapter.3}% +\contentsline {section}{\numberline {3.1}Bending of plate when point load is applied}{7}{section.3.1}% +\contentsline {subsection}{\numberline {3.1.1}Geometry}{7}{subsection.3.1.1}% +\contentsline {subsection}{\numberline {3.1.2}Material}{7}{subsection.3.1.2}% +\contentsline {subsection}{\numberline {3.1.3}Results}{8}{subsection.3.1.3}% +\contentsline {section}{\numberline {3.2}Bending of plate when line load is applied}{8}{section.3.2}% +\contentsline {subsection}{\numberline {3.2.1}Geometry}{8}{subsection.3.2.1}% +\contentsline {subsection}{\numberline {3.2.2}Material}{8}{subsection.3.2.2}% +\contentsline {subsection}{\numberline {3.2.3}Results}{8}{subsection.3.2.3}% +\contentsline {chapter}{\numberline {4}Benchmark 3: Smooth rigid footing on elastic soil}{11}{chapter.4}% +\contentsline {section}{\numberline {4.1}Geometry}{11}{section.4.1}% +\contentsline {section}{\numberline {4.2}Material}{11}{section.4.2}% +\contentsline {section}{\numberline {4.3}Meshing}{11}{section.4.3}% +\contentsline {section}{\numberline {4.4}Results}{11}{section.4.4}% +\contentsline {chapter}{\numberline {5}Benchmark 4: 1D consolidation on elastic soil}{13}{chapter.5}% +\contentsline {section}{\numberline {5.1}Geometry}{13}{section.5.1}% +\contentsline {section}{\numberline {5.2}Materials}{13}{section.5.2}% +\contentsline {section}{\numberline {5.3}Meshing}{13}{section.5.3}% +\contentsline {section}{\numberline {5.4}Calculation}{13}{section.5.4}% +\contentsline {section}{\numberline {5.5}Results}{13}{section.5.5}% +\contentsline {chapter}{Bibliography}{15}{chapter*.18}% diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tps b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tps new file mode 100644 index 000000000000..780ffd86ceb0 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/Kratos_Verification.tps @@ -0,0 +1,26 @@ +[FormatInfo] +Type=TeXnicCenterProjectSessionInformation +Version=2 + +[Frame0] +Flags=0 +ShowCmd=1 +MinPos.x=-1 +MinPos.y=-1 +MaxPos.x=-1 +MaxPos.y=-1 +NormalPos.left=4 +NormalPos.top=26 +NormalPos.right=1556 +NormalPos.bottom=645 +Class=LaTeXView +Document=Kratos_Verification.tex + +[Frame0_View0,0] +TopLine=34 +Cursor=1724 + +[SessionInfo] +FrameCount=1 +ActiveFrame=0 + diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/1d_consolidation_result.png b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/1d_consolidation_result.png new file mode 100644 index 000000000000..386dd75bbb0d Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/1d_consolidation_result.png differ diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/beam_bm_2_1.png b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/beam_bm_2_1.png new file mode 100644 index 000000000000..6d931320b034 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/beam_bm_2_1.png differ diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/beam_bm_2_2.png b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/beam_bm_2_2.png new file mode 100644 index 000000000000..6d931320b034 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/beam_bm_2_2.png differ diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/material_bm_1.png b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/material_bm_1.png new file mode 100644 index 000000000000..3e6831e476d6 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/material_bm_1.png differ diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/materials_rigid_footing_elastic_soil.png b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/materials_rigid_footing_elastic_soil.png new file mode 100644 index 000000000000..bc34e9ef3bbd Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/materials_rigid_footing_elastic_soil.png differ diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/mesh_rigid_footing_elastic_soil.PNG b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/mesh_rigid_footing_elastic_soil.PNG new file mode 100644 index 000000000000..b0e108c77280 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/mesh_rigid_footing_elastic_soil.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/vertical_stress_rigid_footing_elastic_soil.png b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/vertical_stress_rigid_footing_elastic_soil.png new file mode 100644 index 000000000000..c3b2c5fd1071 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/Kratos_Verification/figures/vertical_stress_rigid_footing_elastic_soil.png differ diff --git a/applications/GeoMechanicsApplication/documents/Kratos_Verification/references/kratos_references.bib b/applications/GeoMechanicsApplication/documents/Kratos_Verification/references/kratos_references.bib new file mode 100644 index 000000000000..59dd4295b083 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/Kratos_Verification/references/kratos_references.bib @@ -0,0 +1,10 @@ +% Encoding: UTF-8 + +@Book{Verruijt2001, + title = {SOIL MECHANICS}, + publisher = {Delft University of Technology}, + year = {2001}, + author = {Arnold Verruijt}, +} + +@Comment{jabref-meta: databaseType:bibtex;} diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterCalculating.tex b/applications/GeoMechanicsApplication/documents/tutorials/ChapterCalculating.tex new file mode 100644 index 000000000000..6a602e33bc67 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/ChapterCalculating.tex @@ -0,0 +1,14 @@ + + +TODO \\ + +A staged calculation cannot be calculated via GiD. This has to be done via the command prompt or python. +\begin{enumerate}[resume] + \item Take the template file "MainKratos$\_$multiple$\_$stages$\_$template.py" from ./KratosGeoMechanics/applications/GeoMechanicsApplication. And copy it to the main KratosGeoMechanics directory. Rename the file to "MainKratos.py" + + \item right click on "MainKratos.py" and select "edit". + \item Edit the project$\_$paths variable such that it refers to the correct *.gid files. Note that the file paths should stay within the quotation marks. + + \item In windows explorer, go to the KratosGeoMechanics directory. In the adress-bar, type in: "cmd" and press "enter", such that command prompt is opened while already referring to the correct directory. In the command prompt, type in: "runkratos MainKratos.py". Now the calculation should start running with as many stages as preferred. + +\end{enumerate} \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterCreateGeometry.tex b/applications/GeoMechanicsApplication/documents/tutorials/ChapterCreateGeometry.tex new file mode 100644 index 000000000000..a5ee99ddeec3 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/ChapterCreateGeometry.tex @@ -0,0 +1,84 @@ +\subsection{Create lines} +\begin{enumerate} + \setlength\itemsep{2mm} + + \item In the geometry toolbar click on either: + \begin{itemize} + \setlength\itemsep{2mm} + \item \includegraphics{createLine.png} Create line + + \item \includegraphics{createArc.png} Create arc + + \item \includegraphics{createNurbsLine.png} Create nurbs line + \end{itemize} + \item Create the line by clicking on the domain or fill in the coordinates in the command line below. When the line is finished, press ESC. + + \item \includegraphics{movePoint.png} In order to change the location of the line, press the “move a point” button on the left toolbar. In the domain click on a point of the line to select it. Click somewhere else in the domain or fill in the new coordinates to move the point to that location. + + \item Lines always have to be connected to other lines by points. In order to add extra points on an existing line, there are the following options + + \begin{itemize} + \setlength\itemsep{2mm} + \item \includegraphics{divideLineNrDiv.png} Divide a line in a number of divisions + + \item \includegraphics{divideLineNearPoint.png} Divide a line near a point + + \item \includegraphics{divideLineAtIntersectLine.png} Divide a line on intersecting lines + \end{itemize} + + \end{enumerate} + +\subsection{Create surfaces} + +\begin{enumerate} + \setlength\itemsep{2mm} + + \item To create a surface there are 2 options: + \begin{itemize} + \setlength\itemsep{2mm} + \item \includegraphics{createObject.png} click on create object and choose either: \textbf{Rectangle}, \textbf{Polygon} or \textbf{Circle}. And draw the surface in the geometry view, or fill in the coordinates in the command line. + + \item Create lines as described before. Connect the lines until a closed shape is formed. Click on "Create NURBS surface" \includegraphics{createNurbsSurface.png} and select the lines in the geometry view which should form the boundary of your surface. Press ESC to finish. \\\\ + \textit{ (Note that lines have to be connected through points, when one line finishes halfway on another line, this is not considered as a closed surface. Another point has to be added to the second line to form a closed surface.) } + \end{itemize} + + \item In order to divide a surface into multiple surfaces click on either of the following buttons on the Geometry toolbar: + \begin{itemize} + \setlength\itemsep{2mm} + \item \includegraphics{divideSurfaceInNParts.png} Divide the surface in n even parts + \item \includegraphics{splitSurfaceFromPathOfLines.png} Divide the surface through a path of lines + + \item \includegraphics{intersectSurfaceWithLines.png} Intersect the surface through lines + + \item \includegraphics{intersectMultipleSurfaces.png} Intersect the surface with other surfaces + + \end{itemize} + +\end{enumerate} + +\subsection{Create volumes} + +\begin{enumerate} + \setlength\itemsep{2mm} + \item In order to create volumes there are multiple options: + \begin{itemize} + \setlength\itemsep{2mm} + + \item \includegraphics{createObject.png} click on create object and choose either: \textbf{Sphere}, \textbf{Cylinder}, \textbf{Cone}, \textbf{Prism} or \textbf{Thorus}. And draw the volume in the geometry view, or fill in the coordinates in the command line. + + \item In this option, a volume is created by stretching a surface in the 3rd dimension. + \begin{enumerate} + \setlength\itemsep{2mm} + \item In the top menu bar go to: Utilities -> Copy… + \item In the Copy window set entities type to “Surfaces” + \item In the Copy window set Transformation to “Translation” + \item In the Copy window set the first and second point (there should be a difference between the z values in order to create a volume) + \item In the Copy window set Do extrude to “Volumes” and unselect “Create contacts” in order to create a volume with more than 1 element in the Z-direction + \end{enumerate} + + \item An other option is to create a volume from connected surfaces. Create surfaces and connect them until a closed 3 dimensional shape is formed. Click on "create volume" \includegraphics{createVolume.png} and select the surfaces in the geometry view which should form the boundaries of the volume. Press ESC to finish. + + \end{itemize} + + +\end{enumerate} \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterDefineProblem.tex b/applications/GeoMechanicsApplication/documents/tutorials/ChapterDefineProblem.tex new file mode 100644 index 000000000000..2a1b5e38c872 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/ChapterDefineProblem.tex @@ -0,0 +1,51 @@ +When the geometry is created, the problem can be defined. \\\\ +%In the top menu bar click: Data-> Problem Data and alter the variables to your liking, for explanation of the variables, see Section @@@. + +\subsection{Materials} +todo +%\includegraphics{materialsWindow.png} +%\begin{enumerate} +% \setlength\itemsep{2mm} +% \item In the top menu bar click: Data-> Materials +% \item In the Materials window click on Rename Materials \includegraphics{rename.png} to rename the material from “default material” +% \item In the Materials window enter all the material properties, see section @@ for explanation on the variables +% \item In the Materials window, when all properties are filled. Assign the the material to either Line, Surfaces or Volumes in the geometry view. +% \item In the Materials window, in order to add a new material, click on New material \includegraphics{newMaterial.png} and repeat the aforementioned steps +% \item In the Materials window, the materials can be unassigned by clicking on Unassign and select the lines,surfaces or volumes in the geometry view. +% \item In the Materials window, the materials are shown by clicking on Draw +% +% \item Materials can be exported or imported to/from other GID projects.In the Materials window, click on exchange and select the *.mat file from another project. In the new "Exhange Materials" window, move the materials to your liking and click on apply or save. Reopen de materials window to see your changes. +%\end{enumerate} + +\subsection{Boundary conditions} +todo +%\includegraphics{boundaryConditionsWindow.png} +\begin{enumerate} + \setlength\itemsep{2mm} +% \item In the top menu bar click: Data-> Conditions->Boundary conditions +% \item In the Boundary conditions window, choose the type of boundary (head, flux, pressure, seepage, general). +% \item In the Boundary conditions window, fill in the name of your condition +% \item In the condition table, fill in the boundary condition values (flux or head, depending on the condition type) and the corresponding timesteps. It is also possible to copy the boundary condition values and timesteps from excel. Note that the boundary condition is constant from the last filled in time step. + \item Before the boundary conditions can be assigned to the geometry, it is important to understand the following box:\\ + \includegraphics{assignBoundaryConditionBox.png} + \begin{itemize} + \item Use the text box to fill in the identifier of the condition (for example the condition name) or select an existing boundary condition + \item Click on \includegraphics{assignToLine.png} to assign the boundary condition to lines, click on \includegraphics{assignToSurface.png} to assign the boundary condition to surfaces. + \item Click on \includegraphics{acceptChange.png} to assign the filled in boundary condition values to an existing boundary condition which is selected in the text box. + \item Click on \includegraphics{createNewGroup} to create a new group and assign the group to the geometry (lines or surfaces, depending which option is chosen) + \end{itemize} +% \item When a boundary condition is assigned to the geometry, a new group is created. The groups are shown in the layers and group window in the groups tab. When the layers and group window is not shown: on the Standard Gid Toolbar, click on the layers button \includegraphics{layersButton} +% \item To assign an existing boundary condition to another line/surface, in the groups window, select your group and click on "assign the selected entity to a group" \includegraphics{createNewGroup.png}. Now click on either lines or surfaces and assign your boundary condition to the lines or surfaces in the geometry view. +% \item To unassign an existing boundary condition, in the groups window, select your group and click on "unassign the selected entity from a group" \includegraphics{unassignGroup.png}. Now click on either lines or surfaces and unassign your boundary condition from the lines or surfaces in the geometry view. +\end{enumerate} + +\subsection{Structural elements and interfaces} +\begin{enumerate} + \item To create a structural element, on the top menu bar click on \textit{GeoMechanicsApplication => elements}. + \item From the \textit{Elements} window which appeared, from the top drop-down menu. Select the preferred structural element (Beam, Shell thin corotational, Shell thick corotational, Truss or Cable). The structural element can then be assigned to the geometry. + \item In order to create an interface between the soil and the structural element. Multiple GiD-layers need to be created in GiD. One layer needs to be the layer of the structural elements, the next layer is the soil on one side of the structural element, the next layer being the soil on the other side of the structural element. + + + +\end{enumerate} + diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterGettingStarted.aux b/applications/GeoMechanicsApplication/documents/tutorials/ChapterGettingStarted.aux new file mode 100644 index 000000000000..bef4a9666754 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/ChapterGettingStarted.aux @@ -0,0 +1,43 @@ +\relax +\providecommand\hyper@newdestlabel[2]{} +\providecommand{\transparent@use}[1]{} +\@setckpt{ChapterGettingStarted}{ +\setcounter{page}{4} +\setcounter{equation}{0} +\setcounter{enumi}{6} +\setcounter{enumii}{2} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{2} +\setcounter{section}{0} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +\setcounter{float@type}{4} +\setcounter{AM@survey}{0} +\setcounter{LT@tables}{0} +\setcounter{LT@chunks}{0} +\setcounter{FancyVerbLine}{0} +\setcounter{caption@flags}{0} +\setcounter{ContinuedFloat}{0} +\setcounter{subfigure}{0} +\setcounter{subtable}{0} +\setcounter{r@tfl@t}{0} +\setcounter{section@level}{0} +\setcounter{mn@abspage}{8} +\setcounter{parentequation}{0} +\setcounter{Item}{8} +\setcounter{Hfootnote}{0} +\setcounter{bookmark@seq@number}{0} +\setcounter{currfiledepth}{0} +\setcounter{n_sp_blocks}{0} +\setcounter{n_sp_items}{0} +\setcounter{idxcols}{2} +\setcounter{NAT@ctr}{0} +} diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterGettingStarted.tex b/applications/GeoMechanicsApplication/documents/tutorials/ChapterGettingStarted.tex new file mode 100644 index 000000000000..f9a3b3bac0f0 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/ChapterGettingStarted.tex @@ -0,0 +1,53 @@ +Below is a figure which shows the main window of the GID - pre processor and its different parts. Within the manual, references will be made to these different parts. + +\includegraphics[width=0.9\textwidth]{GIDMainWindow.png} + + + +\begin{enumerate} + \setlength\itemsep{2mm} + + \item Download KratosGeoMechanics from the buildserver (Deltares only) \href{https://build.deltares.nl/viewType.html?buildTypeId=GEOFEA_KratosGeo_Compile}{Download KratosGeoMechanics}. Click on the \includegraphics{artifactsIcon.png} icon of the latest build where all tests succeed download KratosGeoMechanics.zip. + + \item unzip \textbf{KratosGeoMechanics.zip} and place it in a convenient location. + + \item Go to \href{https://www.python.org/downloads/release/python-375/} {Download python 3.7} and download \textit{"Windows x86-64 embeddable zip file"}. + + \item unzip the python zip file. From the unzipped directory, copy: \textbf{"python37.dll"}. And paste it in the \textit{"KratosGeoMechanics"} directory. + + \item Download GID from \href{https://www.gidhome.com/download/official-versions/}{Download GID}. The problemtype is made while using GID version 14*. + + \item In the KratosGeoMechanics directory go to: \newline "applications/GeoMechanicsApplication/custom$\_$problemtype/ \newline GeoMechanicsApplication.gid" + + \item right click and edit \textbf{"GeoMechanicsApplication.win.bat"}. Replace all the paths until \textit{"*\textbackslash\textbackslash Kratos"} with the location of the KratosGeoMechanics dir on your local drive. For example : + replace \textit{"D:\textbackslash\textbackslash src\textbackslash\textbackslash Kratos\textbackslash\textbackslash runkratos"} by \newline \textit{"C:\textbackslash\textbackslash Users\textbackslash\textbackslash noordam\textbackslash\textbackslash Downloads\textbackslash\textbackslash KratosGeoMechanics\textbackslash\textbackslash runkratos"}. Note that the double backslashes are required for path separations. + + \item Copy the \textbf{GeoMechanicsApplication.Gid} problemtype paste it in the GiD problemtypes folder, e.g. : \textit{C:/Program Files/GiD/GiD 14.0.3/problemtypes/} + + \begin{itemize} + \setlength\itemsep{2mm} + \item \textit{When performing this step, GID files can easily be transferred between different PC’s, however admin rights on your computer are required for this step.} + + \item \textit{If you do not have admin rights, it is still possible to use GID and to transfer GID files between different PC’s, however, more effort is required to retain all data. Explanation is given in section @@@.} + \end{itemize} + + \item Open GiD (it is recommended to have your GiD window on your main screen, since GiD pop-up messages appear on your main screen) + + \item If you performed Step 8, perform Step 10.1, else perform Step 10.2. + \begin{enumerate} + \item In the top menu bar choose: Data -> Problem type-> GeoMechanicsApplication + + \item In the top menu bar choose: Data -> Problem type-> Load… and choose file: \textit{GeoMechanicsApplication.gid} from any locations + \end{enumerate} + \item In the top menu bar choose: Utilities -> Preferences. + \item In the Preferences window choose: Grid + \begin{itemize} + \setlength\itemsep{2mm} + \item Alter the domain size to your liking (X Extents / Y Extends) + \item In General options: activate the options as preferred. + \item In Spacing: alter the spacing for which your pointer snaps to a location. + \end{itemize} + + +\end{enumerate} + diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterIntroduction.tex b/applications/GeoMechanicsApplication/documents/tutorials/ChapterIntroduction.tex new file mode 100644 index 000000000000..72bb31a3f011 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/ChapterIntroduction.tex @@ -0,0 +1,7 @@ +%In this manual, it is explained how to use the connection between the \textbf{GID pre/post processor} en the \textbf{DgFlow kernel}. +% +%\textbf{DgFlow} is a kernel which can be used for groundwater flow calculations, DgFlow separates itself from other groundwater flow software with a piping module to calculate piping related issues. The scientific manual can be found @@@@ +% +%The \textbf{GID pre/post processor} is used to assign materials, boundary conditions and to create a mesh for DgFlow, both for 2D and 3D geometries. The complete reference manual for GID can be found here: \href{https://www.gidhome.com/documents/referencemanual/Tabla\%20de\%20Contenidos}{GID Reference Manual}. +% +%The connection is made for \textbf{GiD version 13.0.4}, the connection might work for other versions, but this is not validated.\\ \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterMeshing.tex b/applications/GeoMechanicsApplication/documents/tutorials/ChapterMeshing.tex new file mode 100644 index 000000000000..542b249f8a0e --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/ChapterMeshing.tex @@ -0,0 +1,22 @@ + +Before a calculation can be done with KratosGeoMechanics, it is required to generate the mesh. Every time something is changed in the geometry, the mesh has to be regenerated. So for example: + +\begin{itemize} + \setlength\itemsep{2mm} + \item The geometry has been changed + \item A new or different boundary condition is assigned + \item A different material is assigned to an existing surface or volume +\end{itemize} + +\begin{enumerate} + \setlength\itemsep{2mm} + \item In the top menu bar click: Mesh->Element type to choose the element type of your mesh. For a 2D domain choose either triangle elements or quadrilateral elements. For a 3D domain choose either Tetrahedra, hexahedra or Prism elements. Line elements are automatically set as Bar elements. + \item The size of the mesh can be set locally. +\begin{itemize} + \setlength\itemsep{2mm} + \item In the top menu bar click: "Mesh->Unstructured->Assign sizes on lines/surfaces/volumes" to assign the size of the unstructured mesh on respectively lines,surfaces or volumes. + \item In the top menu bar click: "Mesh->Structured->Assign sizes on lines/surfaces/volumes" to assign the size of the structured mesh on respectively lines,surfaces or volumes. +\end{itemize} + \item To alter the size transition from small elements to large elements in an unstructured mesh, In the top menu bar click: Utilities->Preferences. In the Preferences window, go to Meshing->Unstructured. In this window, the "Unstructured size transition" can be altered. It controls whether the transitions between different element sizes are slow (near to 0) or fast (near to 1), where the default is 0.6. Select the preferred size transition number and click on apply. + +\end{enumerate} diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterPostProcess.tex b/applications/GeoMechanicsApplication/documents/tutorials/ChapterPostProcess.tex new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/applications/GeoMechanicsApplication/documents/tutorials/ChapterTutorial1.tex b/applications/GeoMechanicsApplication/documents/tutorials/ChapterTutorial1.tex new file mode 100644 index 000000000000..29dfa3bf0bc3 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/ChapterTutorial1.tex @@ -0,0 +1,364 @@ + +The first tutorial shows how to create a dike with multiple layers and multiple piezometric levels. Note that this tutorial is meant to show the possibilities of KratosGeoMechanics in GiD, rather than creating a realistic dike. +\section{Geometry} +\begin{enumerate} + + + \item In GiD, press the icon \includegraphics{CreateLine.png} and draw the outlines of your geometry according to Table \ref{tab:tut1_outline}. Make sure to press "Join" in the Create point procedure when connecting the last line to the first point. + +% \begin{table}[h!] +% \centering +% \caption{Outline geometry tutorial 1} +% \label{tab:tut1_outline} +% \begin{tabular}{llll} +% Point ID & x-coordinate & y-coordinate & Escape \\ +% 1 & -50, -15 & 50, -15 & False \\ +% 2 & 50 & -15 & False \\ +% 3 & 40 & 0 & False \\ +% 4 & 10 & 0 & False \\ +% 5 & 0 & 5 & False \\ +% 6 & -5 & 5 & False \\ +% 7 & -15 & 0 & False \\ +% 8 & -50 & 0 & False \\ +% 1 & -50 & -15 & True +% \end{tabular} +% \end{table} + + \begin{table}[h!] + \centering + \caption{Outline geometry tutorial 1} + \label{tab:tut1_outline} + \begin{tabular}{lll} + Line ID & Point 1 (x,y)& Point 2 (x,y) \\ + 1 & -50, -15 & 50, -15 \\ + 2 & 50, -15 & 50, 0 \\ + 3 & 50, 0 & 10, 0 \\ + 4 & 10, 0 & 0, 5 \\ + 5 & 0, 5 & -5, 5 \\ + 6 & -5, 5 & -15, 0 \\ + 7 & -15, 0 & -50, 0 \\ + 8 & -50, 0 & -50, -15 \\ + \end{tabular} + \end{table} + + + \item Now create lines to set the outlines of the soil layers. According to Table \ref{tab:tut1_outline_sl}. +% \begin{table}[h!] +% \centering +% \caption{Outline soil layer tutorial 1} +% \label{tab:tut1_outline_sl} +% \begin{tabular}{llll} +% Point ID & x-coordinate & y-coordinate & Escape \\ +% 9 & -50, -10 & -10 & False \\ +% 10 & 50 & -10 & True \\ +% 7 & -15 & 0 & False \\ +% 4 & 10 & 0 & True \\ +% \end{tabular} +% \end{table} + + + \begin{table}[h!] + \centering + \caption{Outline soil layer tutorial 1} + \label{tab:tut1_outline_sl} + \begin{tabular}{lll} + Line ID & Point 1 (x,y)& Point 2 (x,y) \\ + 9 & (-50, -10) & (50, -10) \\ + 10 & (-15, 0) & (10, 0 ) \\ + \end{tabular} + \end{table} + + + \item Create vertical lines at the location of the turning points of the phreatic level which will be created in a further step, according to Table \ref{tab:tut1_verticals_water}. +% \begin{table}[h!] +% \centering +% \caption{Verticals turning points phreatic line tutorial 1} +% \label{tab:tut1_verticals_water} +% \begin{tabular}{llll} +% Point ID & x-coordinate & y-coordinate & Escape \\ +% 11 & -7.5 & 5 & False \\ +% 12 & -7.5 & -15 & True \\ +% 4 & -15 & 0 & False \\ +% 13 & 10 & 0 & True \\ +% \end{tabular} +% \end{table} + + \begin{table}[h!] + \centering + \caption{Verticals turning points phreatic line tutorial 1} + \label{tab:tut1_verticals_water} + \begin{tabular}{lll} + Line ID & Point 1 (x,y)& Point 2 (x,y) \\ + 11 & (-7.5, 5) & (-7.5, -15) \\ + 12 & (-15, 0) & (10, 0) \\ + \end{tabular} + \end{table} + + + + + \item Create all the intersections between the lines by clicking on the \includegraphics{divideLineAtIntersectLine.png} button and selecting everything. The outlines should look as displayed in Figure \ref{fig:tut1_all_outline}. Further references to line ID's are done using the line ID's as shown in the figure. + + \begin{figure}[h!] + \includegraphics[width=0.9\textwidth]{outlinesTutorial1.png} + \caption{All outlines tutorial 1} + \label{fig:tut1_all_outline} + \end{figure} + + \item Create surfaces by clicking on the \includegraphics{createNurbsSurface.png} button and selecting the lines as displayed in Table \ref{tab:tut1_surfaces}. + + \begin{table}[h!] + \centering + \caption{Surfaces tutorial 1} + \label{tab:tut1_surfaces} + \begin{tabular}{ll} + Surface ID & line ID's \\ + 1 & (7, 27, 35, 33, 21) \\ + 2 & (28, 25, 34, 35) \\ + 3 & (3, 16, 24, 25) \\ + 4 & (33, 36, 13, 22) \\ + 5 & (34, 26, 31, 36) \\ + 6 & (24, 15, 32, 26) \\ + 7 & (18, 29, 27) \\ + 8 & (17, 5, 4, 28, 29) \\ + \end{tabular} + \end{table} + + \item Delete line (19) and the attached point by clicking on the \includegraphics{deleteButton.png} and the \includegraphics{deleteAllButton.png} in the Geometry toolbar. The geometry should look like as displayed in Figure \ref{fig:tut1_geometry}. Further references to surface ID's are made to the ID's as shown in the figure. + + \begin{figure}[h!] + \includegraphics[width=0.9\textwidth]{geometryTut1.png} + \caption{Geometry tutorial 1} + \label{fig:tut1_geometry} + \end{figure} + + +\end{enumerate} +\section{Boundary conditions} + +\begin{enumerate}[resume] + + + \item The next step is setting the boundary conditions. In this tutorial, the side boundaries can move freely in vertical direction; the bottom boundary is fixed. In the top menu bar, select \textit{GeoMechanicsApplication->Dirichlet Constraints}. The window as shown in Figure \ref{fig:tut1_dirichlet_constraints_window} should appear. + \begin{figure}[h!] + \includegraphics[width=0.5\textwidth]{dirichletConstraintsWindow.png} + \caption{Dirichlet constraints window} + \label{fig:tut1_dirichlet_constraints_window} + \end{figure} + + \item For the side boundaries, deselect "\textit{SOLID DISPLACEMENT Y}". Now in the bottom left corner of the Dirichlet Constaints window, fill in "side boundary". In this same window click on the line button \includegraphics{assignToLine.png}. And click on the create new group button, \includegraphics{createNewGroup}. Now select the lines (21, 22, 15, 16) in the geometry and press "ESC". + + \item For the bottom boundary, in the Dirichlet Constaints window, select all the \textit{SOLID DISPLACEMENT} buttons and keep the values at 0. Name this boundary "bottom boundary", and assign this boundary condition to the lines (13, 31 ,32). +\end{enumerate} +\section{Materials} +\begin{enumerate}[resume] + \item Now the materials have to be assigned to the surfaces. In this tutorial, 3 materials will be created. In the top menu bar, select \textit{GeoMechanicsApplication->Elements}. A new window should appear. + + \item In the elements window which appeared, from the top drop-down menu, select "soil-drained". And fill in the values as shown in Figure \ref{fig:tut1_clay_mat}. For the parameter, "UDSM Name", fill in the address of the "MohrCoulomb.dll", including extension. For the description of the Mohr Coulomb parameters, see @@@. Assign the material to the surfaces (1, 2, 3). + + \begin{figure}[h!] + \includegraphics[width=0.5\textwidth]{clayMaterialWindowTut1.png} + \caption{Clay parameters tutorial 1} + \label{fig:tut1_clay_mat} + \end{figure} + + \item For the second material, select "soil-drained" and fill in the parameters as shown in Figure \ref{fig:tut1_sand_mat}. Again for the "UDSM Name" fill in the address if the "MohrCoulomb.dll", including extension. Assign the material to the surfaces (4, 5, 6) + + \begin{figure}[h!] + \includegraphics[width=0.5\textwidth]{sandMaterialWindowTut1.png} + \caption{Sand parameters tutorial 1} + \label{fig:tut1_sand_mat} + \end{figure} + + \item For the last material, again select "soil-drained" and fill in the parameters as shown in Figure \ref{fig:tut1_dike_mat}, again referring to "MohrCoulomb.dll" for "UDSM Name". Assign the material to surfaces (7, 8). + + \begin{figure}[h!] + \includegraphics[width=0.5\textwidth]{dikeMaterialWindowTut1.png} + \caption{Dike parameters tutorial 1} + \label{fig:tut1_dike_mat} + \end{figure} +\end{enumerate} + +\section{Water} +\begin{enumerate}[resume] + \item The first water level to be added is the river water level. Click on \textit{GeoMechanicsApplication -> Dirichlet Constraints}. In the Dirichlet Constraints window, select Fluid Pressure from the top drop-down menu. Fill in the parameters as shown in Figure \ref{fig:tut1_river_level}. Assign this fluid pressure to line 7. + + \begin{figure}[h!] + \includegraphics[width=0.5\textwidth]{riverLevelTut1.png} + \caption{River water level tutorial 1} + \label{fig:tut1_river_level} + \end{figure} + + \item Now rename the previous Fluid pressure condition to "\verb|river_level_surface|". And assign the condition to surface 7 + + \item The water pressure due to the river water level is now set, however since the water level lies above the surface, it is required to explicitly define the normal load due to the water. Click on \textit{GeoMechanicsApplication -> Loads}. From the top drop-down menu in de Loads window, select \textit{Normal Load}. Fill in the values as shown in Figure \ref{fig:tut1_river_load}. Assign the condition to the lines 17 and 18. + + \begin{figure}[h!] + \includegraphics[width=0.5\textwidth]{riverLoadTut1.png} + \caption{River load tutorial 1} + \label{fig:tut1_river_load} + \end{figure} + + \item The water level in the dike is an inclined phreatic line. Click on \textit{GeoMechanicsApplication -> Dirichlet Constraints}. Select \textit{Fluid Pressure} from the top drop-down menu in the Dirichlet Constraints table and fill in the values as shown in Figure \ref{fig:tut1_dike_level}. Assign the condition to surface 8. + + \begin{figure}[h!] + \includegraphics[width=0.5\textwidth]{dikeLevelTut1.png} + \caption{Dike water level tutorial 1} + \label{fig:tut1_dike_level} + \end{figure} + + \item For the last part of the phreatic level, select \textit{fluid pressure}, choose \textit{Hydrostatic} pressure distribution. Set the reference coordinate on -15. In the Fluid pressure table fill in 0 on time 0 and 2; fill in 15 at time 3 and 4. Name the condition \verb|"polder level"| and assign the condition to line 3. + + \item Now for the water level in the aquifer, select \textit{fluid pressure}, choose \textit{Hydrostatic} pressure distribution. Set the reference coordinate on -15. In the Fluid pressure table fill in 0 on time 0 and 2; fill in 18 at time 3 and 4. Name the condition \verb|"aquifer_level"| and assign the condition to surface 4, 5 and 6. + + \item Lastly, select \textit{Interpolate line} pressure distribution, set \textit{Imposed Pressure} on \textit{Table Interpolation} and assign the condition to surface 1, 2 and 3. + +\end{enumerate} +\section{Loads} +\begin{enumerate}[resume] + \item In this tutorial, the only loads will be applied are water loads and the own weight of the soils. The water loads are already applied in the previous section. To apply the soil weight, click on \textit{GeoMechanicsApplication -> Loads} and select \textit{Body Acceleration} from the drop-down menu. + + \item In the Loads window, for \textit{Imposed Body Acceleration Y} select table interpolation. Fill in 0 for time 0; and fill in -9.81 for time 1 and 4. Name this load \verb|"body_surface"| and assign the condition to the surfaces: 1, 2, 3, 4, 5, 6. + + \item For the self weight of the dike, in the Loads window, for \textit{Imposed Body Acceleration Y} select table interpolation. Fill in 0 for time 0 and 1; and fill in -9.81 for time 2 and 4. Name this load \verb|"body_dike"| and assign the condition to the surfaces: 7, 8. + +\end{enumerate} + +\section{Meshing} +\begin{enumerate}[resume] + \item On the top menu bar, click on \textit{Mesh -> Unstructured -> Assign sizes on surfaces}. Fill in 1.0 in the dialog window which pops up. And assign this size on the surfaces 7 and 8. + + \item Now fill in 3.0 in the dialog window and assign this size to the surfaces: 1, 2, 3, 4, 5, 6. + + \item On the top menu bar, click on \textit{Mesh -> Quadratic type -> Quadratic}. Such that quadratic elements are generated. + \item On the top menu bar, click on \textit{Mesh -> Generate mesh...}. A Mesh generation window pops up where the element size of the mesh can be filled in. However, since the mesh size of all the surfaces is already defined in previous steps, the number which is filled in into the mesh generation window does not matter. +\end{enumerate} + + +\section{Project Parameters} +\begin{enumerate}[resume] + \item Before the model can be calculated, the project parameters should be filled in correctly. Click on \textit{GeoMechanicsApplication -> Project Parameters}. The problem data Window should appear. + + \item In the \textit{Problem data} window on the \textit{Problem Data} tab, set the \textit{Start Time} to 0.0 and the \textit{End Time} to 4.0. + + \item For the first calculation in this tutorial, in the \textit{Problem data} window on the \textit{Solver Settings} tab, set \textit{Displacement Relative Tolerance} on 1e-2. Keep the rest of the settings on the default values. And press \textit{Accept}. + +\end{enumerate} + +\section{Calculate} +\begin{enumerate}[resume] + \item In order to calculated, on the top menu bar click on \textit{Calculate -> Calculate} + + \item Calculation progress can be monitored by clicking on \textit{Calculate -> View Process info...} + + \item Make sure to save after the calculation is done +\end{enumerate} + +\section{Post-process part 1} +\begin{enumerate}[resume] + \item After calculation, check the results in the post-process window by clicking on the \includegraphics{togglePostProcess.png} icon on the Standard GiD Toolbar. + + \item As an intermediate check before going on to the next part of the tutorial, check if the Water Pressure, the x-displacement and the y-displacement are calculated correctly. In Post-process, click on \includegraphics{contourFillIcon.png} and select: "WATER PRESSURE", then "DISPLACEMENT -> X-DISPLACEMENT" and lastly,"DISPLACEMENT -> y-DISPLACEMENT". Check if the contours are the same as shown in Figure \ref{fig:tut1_p1_results} + + \begin{figure}[h!] + \includegraphics[width=\textwidth]{resultsTutorial1Part1.png} + \caption{Contour results tutorial 1 part 1, top to bottom: water pressure, x-displacement, y-displacement} + \label{fig:tut1_p1_results} + \end{figure} + + \item Go back to the pre-process window. If the results are equal go on to the next part of the tutorial, if not, check if all input is correctly filled in. + +\end{enumerate} + +\section{Staged construction} +\begin{enumerate}[resume] + \item While Kratos GeoMechanics can handle staged calculation, the GiD problemtype can not. In order to perform a staged calculation, some additional actions have to be performed within and outside the Gid pre-processor. The following stages will be added: + \begin{itemize} + \item Initial stage + \item Addition of dike load + \item Addition of daily water level + \item High water level + \end{itemize} + + \item Stage 1: + \begin{enumerate} + \item Save the existing file as \verb|"tutorial_1_stage_1"| + + \item Go to \textit{GeoMechanicsApplication -> Dirichlet Constraints -> Excavation}. Select the option \textit{Deactivate soil}. Name the condition \verb|dike_excavation| and assign the condition to the surfaces 7 and 8. + + \item Go to \textit{GeoMechanicsApplication -> Problem data}. On the Problem data tab, set start and end time from 0.0 to 1.0. + + \item On the Solver Settings tab, set Solution type to K0- procedure. And set the Displacement Relative Tolerance on 1e-3. + + \item Re-mesh. + + \item Click on Calculate and then cancel process. Note that clicking on Calculate is necessary to generate the input files. Results of the in between stages are not relevant, therefore it is not required to wait until the calculation is finished. + \item Save the project again + \end{enumerate} + + \item Stage 2 + \begin{enumerate} + \item Save the existing file as \verb|"tutorial_1_stage_2"| + + \item Go to \textit{GeoMechanicsApplication -> Dirichlet Constraints -> Excavation}. Deselect the option \textit{Deactivate soil} of the \verb|dike_excavation| condition. + + \item Go to \textit{GeoMechanicsApplication -> Problem data}. On the Problem data tab, set start and end time from 1.0 to 2.0. + + \item On the Solver Settings tab, set Solution type to Quasi-Static. + + \item Re-mesh. + + \item Click on Calculate and then cancel process. + \item Save the project again + \end{enumerate} + + \item Stage 3 + \begin{enumerate} + \item Save the existing file as \verb|"tutorial_1_stage_3"| + + \item Go to \textit{GeoMechanicsApplication -> Problem data}. On the Problem data tab, set start and end time from 2.0 to 3.0. + + \item Click on Calculate and then cancel process. + + \item Save the project again + \end{enumerate} + + \item Stage 4 + \begin{enumerate} + \item Save the existing file as \verb|"tutorial_1_stage_4"| + + \item Go to \textit{GeoMechanicsApplication -> Problem data}. On the Problem data tab, set start and end time from 3.0 to 4.0. + + \item Go to \textit{GeoMechanicsApplication -> Dirichlet Constraints -> Fluid Pressure}, set Y 2 of the dike \verb|dike_level| condition on -19. + + \item Click on Calculate and then cancel process. + + \item Save the project again + \end{enumerate} + +\end{enumerate} + +\section{Calculate staged construction} +A staged calculation cannot be calculated via GiD. This has to be done via the command prompt or python. +\begin{enumerate}[resume] + \item Take the template file "MainKratos$\_$multiple$\_$stages$\_$template.py" from ./KratosGeoMechanics/applications/GeoMechanicsApplication. And copy it to the main KratosGeoMechanics directory. Rename the file to "MainKratos.py" + + \item right click on "MainKratos.py" and select "edit". + \item Edit the project$\_$paths variable such that it refers to the correct *.gid files. Note that the file paths should stay within the quotation marks. + + \item In windows explorer, go to the KratosGeoMechanics directory. In the adress-bar, type in: "cmd" and press "enter", such that command prompt is opened while already referring to the correct directory. In the command prompt, type in: "runkratos MainKratos.py". Now the calculation should start running with as many stages as preferred. + +\end{enumerate} + +\section{Post-process part 2} +when all the stages are calculated, all the stages can be viewed separately in post process. + +\begin{enumerate}[resume] + \item In GiD go to post-processing. + \item Select "Open PostProcess" and go to the directory of your preferred stage. Click on the *.bin file to open the postprocess file. + \item Note that "DISPLACEMENT" shows the displacement of the current stage. "TOTAL$\_$DISPLACEMENT" shows the total displacement over the previously calculated stages. + +\end{enumerate} + + + diff --git a/applications/GeoMechanicsApplication/documents/tutorials/deltares_manual.cls b/applications/GeoMechanicsApplication/documents/tutorials/deltares_manual.cls new file mode 100644 index 000000000000..1c7a055f014b --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/deltares_manual.cls @@ -0,0 +1,1880 @@ +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesClass{deltares_manual} + [2014/04/01 v1.0 Standard LaTeX document class] +\DeclareOption{onecolumn}{\OptionNotUsed} +\makeatletter + +\newif\if@ddraft% deltares draft +\@ddraftfalse +\DeclareOption{ddraft}{% + \@ddrafttrue% +} +\newif\if@dutch +\@dutchfalse +\DeclareOption{dutch}{% + \@dutchtrue% +} +\newif\if@spanish +\@spanishfalse +\DeclareOption{spanish}{% + \@spanishtrue% +} +\newif\if@signature +\@signaturefalse +\DeclareOption{signature}{% + \@signaturetrue% +} +\newif\if@druler% deltares ruler +\@drulerfalse +\DeclareOption{druler}{% + \@drulertrue% +} +\newif\if@dbiblatex% deltares biblatex +\@dbiblatexfalse +\DeclareOption{biblatex}{% + \@dbiblatextrue% +} +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}} +\ProcessOptions\relax +%\LoadClass[11pt,twoside,openright,a4paper,titlepage]{report} +\LoadClass[11pt,twoside,a4paper,titlepage]{report} +%------------------------------------------------------------------------------ +% +% Change to Helvetica font +% +%\usepackage{hvmaths} % commercial +% +\usepackage[scaled=.92]{helvet} +\def\rmdefault{phv} +\DeclareMathSizes{\@xipt}{\@xiipt}{8}{6} +\renewcommand{\ttdefault}{pcr} % courier lettertype, needed for bold face in verbatim environment +% +%\usepackage{frutiger} % font van geo-systems manuals +%------------------------------------------------------------------------------ +% Declaring the letters as OML/phv/m/it does not change the font. +% However, upon changing it to OT1/phv/m/it characters such as +% <, > and greek characters are lost. +% +%\DeclareSymbolFont{letters} {OML}{phv}{m}{it} +%\DeclareSymbolFont{letters} {OT1}{phv}{m}{it} +% +%\DeclareSymbolFont{operators} {OT1}{phv}{m}{n} +%\DeclareSymbolFont{symbols} {OMS}{phv}{m}{n} +%\DeclareSymbolFont{largesymbols}{OMX}{phv}{m}{n} +%\DeclareSymbolFont{bold} {OT1}{phv}{bx}{n} +%\DeclareSymbolFont{italic} {OT1}{phv}{m}{it} +%\renewcommand{\familydefault}{phv} + +%------------------------------------------------------------------------------ +\usepackage{sectsty} % to set section fonts +%\allsectionsfont{\fontfamily{cmss}\selectfont} +%\allsectionsfont{\fontfamily{pag}\selectfont} % AvantGarde +%\allsectionsfont{\fontfamily{pbk}\selectfont} % bookman +%\allsectionsfont{\fontfamily{pch}\selectfont} % Charter +%\allsectionsfont{\fontfamily{pcr}\selectfont} % Courier +%\allsectionsfont{\fontfamily{pnc}\selectfont} % New Century Schoolbook +%\allsectionsfont{\fontfamily{ppl}\selectfont} % palatino +%\allsectionsfont{\fontfamily{ptm}\selectfont} % times +%\allsectionsfont{\fontfamily{put}\selectfont} % utopia +%\allsectionsfont{\fontfamily{phv}\selectfont} % helvetica + +\allsectionsfont{\fontfamily{phv}\selectfont} % helvetica + +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[pdftex]{graphicx} +\usepackage{epstopdf} +\usepackage{color} +\usepackage{frcursive} % needed for 'write' letter (French Cursive), use in processes library +\usepackage{float} % needed to force the location of figures \begin{figure}[H] +\usepackage{textcomp} % needed for the promille sign: \textperthousand +\usepackage[final]{pdfpages} % needed for cover pages + +\if@dutch + \usepackage[dutch]{babel} +\else + \if@spanish + \usepackage[spanish]{babel} + \else + \usepackage[english]{babel} + \fi +\fi + +\usepackage{svn-multi} +\usepackage{tabularx} +\usepackage{longtable} +\usepackage{verbatim} +\usepackage{fancyvrb} % needed for framed verbatim environment +\usepackage{calc} % adding, substracting, multiplying of lengths +\usepackage{wrapfig} +\usepackage{caption} +\usepackage{subcaption} % two or more figures in a figure-environment +\usepackage{url} +\usepackage{moreverb} +\usepackage[smallscripts]{moresize} +\usepackage{rotating} % needed for rotating text in tables +\usepackage{nameref} +\usepackage{import} % needed for nested \input{...} -> \import{...}{...} +\usepackage{marginnote} % needed to place the word TODO in the margin, also when it is used in tables + +\usepackage{amstext} % for \text command in math environment +% +% to align equations left add [fleqn] as option to amsmath +% +\usepackage[fleqn]{amsmath} +\usepackage{amssymb} +\usepackage{paralist} % inline enumeration + +\usepackage[detect-all=true, product-units=power, detect-family=false, math-micro=\mu, math-rm=\selectfont, text-rm=\sffamily]{siunitx} +\AtBeginDocument{\sisetup{math-rm=\selectfont, text-rm=\sffamily}} + +%\usepackage[noabbrev]{cleveref} + +\usepackage{xspace} % needed for spaces behind a macro, but no space before punctuation +\usepackage{colortbl} % colour the cells and rows +\usepackage{lastpage} +\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox: needed for conditional list of figures and list of tables +\usepackage{nomencl} +\usepackage[intoc]{nomentbl} +\usepackage{bookmark} +\usepackage{currfile} % needed to detect the directory of the current tex-file +\hypersetup{destlabel, pagebackref, pdfborder={0 0 0}, bookmarksnumbered=true, colorlinks=true, linkcolor=dbluelink, citecolor=dbluelink, urlcolor=dbluelink} +%------------------------------------------------------------------------------ + +\hoffset -1in \voffset -1in +\setlength{\baselineskip}{4.5mm} +\linespread{0.941} + +\topmargin 2\baselineskip +\headheight 2\baselineskip +\headsep 2\baselineskip +% until text = \topmargin + \headheight + \headsep == 6\baselineskip +\setlength{\textheight}{297mm-6\baselineskip-6\baselineskip} +\footskip 3\baselineskip +%foothoogte 2\baselineskip +% 1.5cm remaining + +\oddsidemargin 35mm +\evensidemargin 30mm +\setlength{\textwidth}{210mm-65mm} % 145mm + +\setlength{\marginparwidth}{18mm} +\setlength{\marginparsep}{4.5mm} +\let\oldmarginpar\marginpar +\renewcommand\marginpar[1]{\-\oldmarginpar[\raggedleft\footnotesize #1]% +{\raggedright\footnotesize #1}} + +\widowpenalty=3000 +\clubpenalty=3000 + +%------------------------------------------------------------------------------ +% +% front- and mainmatter commands as known from book.cls, now extended with +% pagestyle, such that page numbers are: i,ii, and 1 of 10, 2 of 10, etc. +% respectively. front- and mainmatter commands automatically set in +% \reporttitle +\newif\if@mainmatter \@mainmattertrue +\newcommand\frontmatter{% + \cleardoublepage + \@mainmatterfalse + \pagenumbering{roman}% + \pagestyle{frontmatterplain}% + \if@druler + \AddToShipoutPicture{\BackgroundRuler} + \fi +} +\newcommand\mainmatter{% + \cleardoublepage + \@mainmattertrue + \pagenumbering{arabic} + \pagestyle{headings} + \if@druler + \AddToShipoutPicture{\BackgroundRuler} + \fi +} +\if@druler + \usepackage{deltares_ruler} +\fi + +%------------------------------------------------------------------------------ +% +% copy of tweaklist.sty, to adjust itemize, enumerate and description +% +\def\enumhook{} +\def\enumhooki{} +\def\enumhookii{} +\def\enumhookiii{} +\def\enumhookiv{} +\def\itemhook{} +\def\itemhooki{} +\def\itemhookii{} +\def\itemhookiii{} +\def\itemhookiv{} +\def\descripthook{} + +\def\enumerate{% + \ifnum \@enumdepth >\thr@@\@toodeep\else + \advance\@enumdepth\@ne + \edef\@enumctr{enum\romannumeral\the\@enumdepth}% + \expandafter + \list + \csname label\@enumctr\endcsname + {\usecounter\@enumctr\def\makelabel##1{\hss\llap{##1}}% + \enumhook \csname enumhook\romannumeral\the\@enumdepth\endcsname}% + \fi} +\def\itemize{% + \ifnum \@itemdepth >\thr@@\@toodeep\else + \advance\@itemdepth\@ne + \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}% + \expandafter + \list + \csname\@itemitem\endcsname + {\def\makelabel##1{\hss\llap{##1}}% + \itemhook \csname itemhook\romannumeral\the\@itemdepth\endcsname}% + \fi} +\renewenvironment{description} + {\list{}{\labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel\descripthook}} + {\endlist} + +\renewcommand{\itemhook}{% + \setlength{\topsep}{\baselineskip/2}% + \setlength{\itemsep}{0pt}% + \setlength{\labelwidth}{1em}% + \setlength{\labelsep}{2.25mm}% + \setlength{\leftmargin}{1em+2.25mm}% + \setlength{\parskip}{0pt}% +}% +\renewcommand{\enumhooki}{% + \setlength{\topsep}{\baselineskip/2}% + \setlength{\itemsep}{0pt}% + \setlength{\labelwidth}{1em}% + \setlength{\labelsep}{2.25mm}% + \setlength{\leftmargin}{1em+2.25mm}% + \setlength{\parskip}{0pt}% +} +\renewcommand{\enumhookii}{% + \setlength{\topsep}{\baselineskip/2}% + \setlength{\itemsep}{0pt}% + \setlength{\labelwidth}{2em}% + \setlength{\labelsep}{2.25mm}% + \setlength{\leftmargin}{2em+2.25mm}% + \setlength{\parskip}{0pt}% +} +\renewcommand{\enumhookiii}{% + \setlength{\topsep}{\baselineskip/2}% + \setlength{\itemsep}{0pt}% + \setlength{\labelwidth}{3em}% + \setlength{\labelsep}{2.25mm}% + \setlength{\leftmargin}{3em+2.25mm}% + \setlength{\parskip}{0pt}% +} +\renewcommand{\enumhookiv}{% + \setlength{\topsep}{\baselineskip/2}% + \setlength{\itemsep}{0pt}% + \setlength{\labelwidth}{4em}% + \setlength{\labelsep}{2.25mm}% + \setlength{\leftmargin}{4em+2.25mm}% + \setlength{\parskip}{0pt}% +} +\renewcommand{\descripthook}{% + \setlength{\topsep}{\baselineskip/2}% + \setlength{\itemsep}{0pt}% + \setlength{\labelwidth}{4.5mm}% + \setlength{\labelsep}{4.5mm}% + \setlength{\leftmargin}{9.0mm}% + \setlength{\parskip}{0pt}% +} +%------------------------------------------------------------------------------ +% +% newcommand for tableofcontents, listoffigures, listotables; taken from report.sty and macro MakeUppercase removed +% 4 nov 2008 Jan Mooiman +% +\setcounter{tocdepth}{3} % i.e. chapter, section, subsection and subsubsection + +\renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.7em}} +\renewcommand*\l@subsection{\@dottedtocline{2}{4.2em}{3.6em}} +\renewcommand*\l@subsubsection{\@dottedtocline{3}{7.8em}{4.5em}} +\renewcommand*\l@paragraph{\@dottedtocline{4}{12.3em}{5.4em}} +\renewcommand*\l@subparagraph{\@dottedtocline{5}{17.7em}{6.3em}} +\renewcommand*\l@figure{\l@section} +\renewcommand*\l@table{\l@figure} + +\AtEndEnvironment{figure}{\gdef\there@is@a@figure{}\label{fig:was:used:in:doc}}% +\AtEndDocument{\ifdefined\there@is@a@figure\label{fig:was:used:in:doc}\fi}% +\newcommand{\conditionalLoF}{\@ifundefined{r@fig:was:used:in:doc}{}{\listofFigures}}% + +\AtBeginEnvironment{longtable}{\gdef\there@is@a@table{}\label{table:was:used:in:doc}}% +\AtEndEnvironment{table}{\gdef\there@is@a@table{}\label{table:was:used:in:doc}}% +\AtEndDocument{\ifdefined\there@is@a@table\label{table:was:used:in:doc}\fi}% +\newcommand{\conditionalLoT}{\@ifundefined{r@table:was:used:in:doc}{}{\listofTables}}% + +\renewcommand\tableofcontents{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \begingroup + \chapter*{\contentsname + \@mkboth{% + \contentsname}{\contentsname}}% + \parskip\z@% + \@starttoc{toc}% + \if@restonecol\twocolumn\fi + \endgroup + } +\newcommand\listofFigures{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \begingroup + \nonumchapter{\listfigurename}% + \@mkboth{\listfigurename}% + {\listfigurename}% + \parskip\z@% + \@starttoc{lof}% + \if@restonecol\twocolumn\fi + \endgroup + } +\newcommand\listofTables{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \begingroup + \nonumchapter{\listtablename}% + \@mkboth{% + \listtablename}% + {\listtablename}% + \parskip\z@% + \@starttoc{lot}% + \if@restonecol\twocolumn\fi + \endgroup + } +\newcommand\listofPhotos{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \begingroup + \nonumchapter{\listtablename}% + \@mkboth{% + \listtablename}% + {\listtablename}% + \parskip\z@% + \@starttoc{lot}% + \if@restonecol\twocolumn\fi + \endgroup + } +%------------------------------------------------------------------------------ +\if@ddraft + \def\draftname{}% + \AtBeginDocument{% + \RequirePackage{draftwatermark}% + \SetWatermarkAngle{54.7}% + \SetWatermarkScale{5}% + \SetWatermarkFontSize{1cm}% + \SetWatermarkLightness{0.92}% + \SetWatermarkText{DRAFT}% + + \renewcommand\sc@watermark{% + \setlength{\@tempdimb}{.63\paperwidth}% + \setlength{\@tempdimc}{-.58\paperheight}% + \put(\strip@pt\@tempdimb,\strip@pt\@tempdimc){% + \makebox(0,0){\rotatebox{\sc@wm@angle}{% + \scalebox{\sc@wm@scale}{% + \expandafter\expandafter\expandafter\textcolor + \expandafter\sc@wm@colormodel\expandafter{\sc@wm@colorspecs}{% + \fontsize{\sc@wm@fontsize}{10.0\sc@wm@fontsize} + \selectfont + \sc@wm@text}}}}}} + } +\else + \def\draftname{} +\fi +\def\ds@draft{\overfullrule 5pt \@drafttrue} + +\if@dutch + \def\@Version{Versie: \@version.\svnrev} +\else + \def\@Version{Version: \@version.\svnrev} +\fi +\def\svn@revinit{00} +\let\svnrev\svn@revinit\let\@svn@rev\svn@revinit + +\if@dutch + \newcommand{\monthname}{% + \ifcase\month\or januari \or februari% + \or maart\or april \or mei% + \or juni\or juli \or augustus% + \or september \or oktober \or november% + \or december\fi}% +\else + \newcommand{\monthname}{% + \ifcase\month\or January\or February% + \or March\or April\or May% + \or June\or July\or August% + \or September\or October\or November% + \or December\fi}% +\fi + +\raggedbottom + +\def\title#1{\gdef\@title{#1}} +\def\subtitle#1{\gdef\@subtitle{#1}} +\def\manualtype#1{\gdef\@manualtype{#1}} +\def\distribution#1{\gdef\@distribution{#1}} +\def\version#1{\gdef\@version{#1}} +\def\author#1{\gdef\@author{#1}} + +\def\@title{use \texttt{$\backslash$title\{\ldots\}}} +\def\@subtitle{use \texttt{$\backslash$subtitle\{\ldots\}}} +\def\@manualtype{use \texttt{$\backslash$manualtype\{\ldots\}}} +\def\@version{use \texttt{$\backslash$version\{\ldots\}}} +\def\@distribution{} +\def\@author{} + +\newcommand{\thechap}{$\;$\leftmark{}$\;$} +\renewcommand\today{% + \number\day\space\monthname\space\number\year% +} +% New column type, to assure parskip in tabular environment (see macro \summary) +\newcolumntype{P}[1]{>{% + \parskip=1\baselineskip% + \advance\parskip by 0pt plus 2pt% + \setlength{\parfillskip}{30pt plus 1fil}}p{#1}% +} +%------------------------------------------------------------------------------ + +%\def\tiny{\@setsize\tiny{7pt}\vipt\@vipt} +%\def\scriptsize{\@setsize\scriptsize{9.5pt}\viiipt\@viiipt} +%\def\large{\@setsize\large{14pt}\xiipt\@xiipt} +%\def\Large{\@setsize\Large{18pt}\xivpt\@xivpt} +%\def\LARGE{\@setsize\LARGE{22pt}\xviipt\@xviipt} +%\def\huge{\@setsize\huge{25pt}\xxpt\@xxpt} +%\def\Huge{\@setsize\Huge{30pt}\xxvpt\@xxvpt} +%\def\HUGE{\@setsize\Huge{40pt}\xxvpt\@xxvpt} + +%\def\tiny{\@setsize\tiny{7.33pt}\vipt\@vipt} +%\def\scriptsize{\@setsize\scriptsize{8.5pt}\viiipt\@viiipt} +%\def\footnotesize{\@setsize\footnotesize{9.25pt}\viiipt\@viiipt} +%\def\small{\@setsize\small{10.00pt}\viiipt\@viiipt} +%%\def\normalsize{\@setsize\normalsize{10.95pt}\viiipt\@viiipt} +%\def\large{\@setsize\large{11.75pt}\xiipt\@xiipt} +%\def\Large{\@setsize\Large{14.10pt}\xivpt\@xivpt} +%\def\LARGE{\@setsize\LARGE{15.85}\xviipt\@xviipt} +%\def\huge{\@setsize\huge{19.02}\xxpt\@xxpt} +%\def\Huge{\@setsize\Huge{22.82}\xxvpt\@xxvpt} +%\def\HUGE{\@setsize\Huge{30pt}\xxvpt\@xxvpt} + +\def\title#1{\gdef\@title{\selectfont #1}} +\def\subtitle#1{\gdef\@subtitle{\selectfont #1}} +\def\author#1{\gdef\@author{\selectfont #1}} +%\def\reporttype#1{\gdef\@reporttype{\selectfont #1}} +%\def\reportdate#1{\gdef\@reportdate{\selectfont #1}} + +\long\def\approvali#1{\gdef\@approvali{#1}} +\long\def\approvalii#1{\gdef\@approvalii{#1}} +\long\def\approvaliii#1{\gdef\@approvaliii{#1}} +\long\def\approvaliv#1{\gdef\@approvaliv{#1}} +\long\def\authori#1{\gdef\@authori{#1}} +\long\def\authorii#1{\gdef\@authorii{#1}} +\long\def\authoriii#1{\gdef\@authoriii{#1}} +\long\def\authoriv#1{\gdef\@authoriv{#1}} +\long\def\classification#1{\gdef\@classification{#1}} +\long\def\client#1{\gdef\@client{#1}} +\long\def\datei#1{\gdef\@datei{#1}} +\long\def\dateii#1{\gdef\@dateii{#1}} +\long\def\dateiii#1{\gdef\@dateiii{#1}} +\long\def\dateiv#1{\gdef\@dateiv{#1}} +\long\def\keywords#1{\gdef\@keywords{#1}} +\long\def\projectnumber#1{\gdef\@projectnumber{#1}} +\long\def\reference#1{\gdef\@reference{#1}} +\long\def\references#1{\gdef\@references{#1}} +\long\def\revieweri#1{\gdef\@revieweri{#1}} +\long\def\reviewerii#1{\gdef\@reviewerii{#1}} +\long\def\revieweriii#1{\gdef\@revieweriii{#1}} +\long\def\revieweriv#1{\gdef\@revieweriv{#1}} +\long\def\status#1{\gdef\@status{#1}} +\long\def\summary#1{\gdef\@summary{#1}} +\long\def\versioni#1{\gdef\@versioni{#1}} +\long\def\versionii#1{\gdef\@versionii{#1}} +\long\def\versioniii#1{\gdef\@versioniii{#1}} +\long\def\versioniv#1{\gdef\@versioniv{#1}} + +\long\def\@approvali{\tiny use \texttt{$\backslash$approvali\{\ldots\}}} +\long\def\@approvalii{} +\long\def\@approvaliii{} +\long\def\@approvaliv{} +\long\def\@authori{\tiny use \texttt{$\backslash$authori\{\ldots\}}} +\long\def\@authorii{} +\long\def\@authoriii{} +\long\def\@authoriv{} +\long\def\@classification{use \texttt{$\backslash$classification\{\ldots\}}} +\long\def\@client{use \texttt{$\backslash$client\{\ldots\}}} +\long\def\@datei{\tiny use \texttt{$\backslash$datei\{\ldots\}}} +\long\def\@dateii{} +\long\def\@dateiii{} +\long\def\@dateiv{} +\long\def\@keywords{use \texttt{$\backslash$keywords\{\ldots\}}} +\long\def\@projectnumber{use \texttt{$\backslash$projectnumber\{\ldots\}}} +\long\def\@reference{use \texttt{$\backslash$reference\{\ldots\}}} +\long\def\@references{use \texttt{$\backslash$references\{\ldots\}}} +\long\def\@revieweri{\tiny use \texttt{$\backslash$revieweri\{\ldots\}}} +\long\def\@reviewerii{} +\long\def\@revieweriii{} +\long\def\@revieweriv{} +\long\def\@status{use \texttt{$\backslash$status\{\ldots\}}} +\long\def\@summary{use \texttt{$\backslash$summary\{\ldots\}}} +\long\def\@versioni{\tiny use \texttt{$\backslash$versioni\{\ldots\}}} +\long\def\@versionii{} +\long\def\@versioniii{} +\long\def\@versioniv{} +% +%------------------------------------------------------------------------------ +% +% TITLE PAGE +% +%------------------------------------------------------------------------------ +% +\newcommand{\helv}{% +\fontfamily{phv}\selectfont} + +\RequirePackage{transparent} +\definecolor{dbluelink}{RGB}{000,000,100} % the colour of hyper links in the pdf-document (daaark blue) +\definecolor{dblue}{RGB}{000,139,191} % the colour of deltares-logo.pdf +\definecolor{dname}{RGB}{150,183,197} % the colour of deltares-logo.pdf +\definecolor{dmetallic}{RGB}{128,169,189} +\definecolor{dsand}{RGB}{160,158,141} +\definecolor{dgreen}{RGB}{180,211,0} +\definecolor{dorange}{RGB}{255,114,0} +\definecolor{dcyclaam}{RGB}{235,0,115} +\definecolor{dcyan}{RGB}{0,196,214} +\definecolor{dgrey1}{RGB}{150,150,150} +\definecolor{dgrey2}{RGB}{180,180,180} +\definecolor{dgrey3}{RGB}{210,210,210} +\definecolor{dgrey4}{RGB}{232,232,232} + + +\def\maketitle{ + \newpage + \thispagestyle{empty} + \setcounter{page}{1} + + \hspace*{80pt}{\LARGE\bf \draftname} + + \vskip 200pt plus \z@ minus \z@ + \hangindent 80pt \hspace*{80pt}{\helv \HUGE\bf \helv \@title \par} + \vfil\vfil + \hangindent 80pt \hspace*{80pt}{\baselineskip 14pt \Large\bf \helv \@subtitle \par} + \vfil + \hangindent 80pt \hspace*{80pt}{\Large \bf \helv \@manualtype \par} + \vfil\vfil\vfil + \hangindent 80pt \hspace*{80pt}{\Large \bf \helv \@distribution \par} + \vfil\vfil\vfil + \hangindent 80pt \hspace*{80pt}{\helv \@author \par} + \vfil +\if@dutch + \hangindent 80pt \hspace*{80pt}{\helv Versie: \@version\newline + SVN Revisie: \svnrev \par} +\else + \if@spanish + \hangindent 80pt \hspace*{80pt}{\helv Versi\'on: \@version\newline + SVN Revisi\'on: \svnrev \par} + \else + \hangindent 80pt \hspace*{80pt}{\helv Version: \@version\newline + SVN Revision: \svnrev \par} + \fi +\fi + \hangindent 80pt \hspace*{80pt}{\helv \@date \par} + \vfil + + \clearpage + \let\maketitle\relax +} +% +%------------------------------------------------------------------------------ +% Signature GB +%------------------------------------------------------------------------------ +% +\newcommand{\signaturegb}{ + {\footnotesize\textbf{Title}} \newline + \@title + + \begin{tabular}{@{}p{39.5mm}p{39.5mm}p{41.0mm}p{\textwidth-120.0mm-42pt}} + \footnotesize{\textbf{Client}} & \footnotesize{\textbf{Project}} & + \footnotesize{\textbf{Reference}} & \footnotesize{\textbf{Pages}} \\ + \@client & \@projectnumber & \@reference & \pageref*{LastPage} + \end{tabular} + + {\footnotesize\textbf{Classification}} \newline + \@classification + + {\footnotesize\textbf{Keywords}} \newline + \@keywords + + {\footnotesize\textbf{Summary}} \newline + \@summary + + {\footnotesize\textbf{References}} \newline + \@references + + \vspace{3\baselineskip} + {{\footnotesize + %\begin{tabular}{p{18mm}@{}p{20mm}@{}p{25mm}@{}p{12mm}@{}p{25mm}@{}p{12mm}@{}p{25mm}@{}p{12mm}} \hline + \begin{tabular}{p{15mm-2pt}@{}p{20mm-2pt}@{}p{25mm-2pt}@{}p{12mm}@{}p{25mm-2pt}@{}p{12mm}@{}p{25mm-2pt}@{}p{\textwidth-133mm-1pt}} \hline + \rowcolor{dgrey4}\rule{0in}{2ex}\!\! + \textbf{Version} & \textbf{Date} & \textbf{Author} & \textbf{Initials} & \textbf{Review} & \textbf{Initials} & \textbf{Approval} & \textbf{Initials} \\ \hline + \@versioni & \@datei & \@authori & & \@revieweri && \@approvali & \\ \hline + \@versionii & \@dateii & \@authorii & & \@reviewerii && \@approvalii & \\ \hline + \@versioniii & \@dateiii & \@authoriii & & \@revieweriii && \@approvaliii & \\ \hline + \@versioniv & \@dateiv & \@authoriv & & \@revieweriv && \@approvaliv & \\ \hline + \end{tabular} + }} + + \vfill + {\footnotesize\textbf{Status}} \newline + \@status +} +% +%------------------------------------------------------------------------------ +% Signature NL +%------------------------------------------------------------------------------ +% +\newcommand{\signaturenl}{ + {\footnotesize\textbf{Titel}} \newline + \@title + + \begin{tabular}{@{}p{39.5mm}p{39.5mm}p{41.0mm}p{\textwidth-120.0mm-42pt}} + \footnotesize{\textbf{Opdrachtgever}} & \footnotesize{\textbf{Project}} & + \footnotesize{\textbf{Kenmerk}} & \footnotesize{\textbf{Pagina's}} \\ + \@client & \@projectnumber & \@reference & \pageref*{LastPage} + \end{tabular} + + {\footnotesize\textbf{Classificatie}} \newline + \@classification + + {\footnotesize\textbf{Trefwoorden}} \newline + \@keywords + + {\footnotesize\textbf{Samenvatting}} \newline + \@summary + + {\footnotesize\textbf{Referenties}} \newline + \@references + + \vspace{3\baselineskip} + {{\footnotesize + \begin{tabular}{p{14mm-2pt}@{}p{20mm-2pt}@{}p{25mm-2pt}@{}p{12mm}@{}p{25mm-2pt}@{}p{12mm}@{}p{25mm-2pt}@{}p{\textwidth-133mm-1pt}} \hline + \rowcolor{dgrey4} \rule{0in}{2ex}\!\! + \textbf{Versie} & \textbf{Datum} & \textbf{Auteur} & \textbf{Paraaf} & \textbf{Review} & \textbf{Paraaf} & \textbf{Goedkeuring} & \textbf{Paraaf} \\ \hline + \@versioni & \@datei & \@authori & & \@revieweri && \@approvali & \\ \hline + \@versionii & \@dateii & \@authorii & & \@reviewerii && \@approvalii & \\ \hline + \@versioniii & \@dateiii & \@authoriii & & \@revieweriii && \@approvaliii & \\ \hline + \@versioniv & \@dateiv & \@authoriv & & \@revieweriv && \@approvaliv & \\ \hline + \end{tabular} + }} + + \vfill + {\footnotesize\textbf{Status}} \newline + \@status +} +% +%------------------------------------------------------------------------------ +% Copyright GB, NL, ESP +%------------------------------------------------------------------------------ +% +\newcommand{\copyrightGB}{ + Copyright {\copyright} \number\year~\Deltares\\ + All rights reserved. No part of this document may be reproduced in any form by print, + photo print, photo copy, microfilm or any other means, without written permission from the + publisher: Deltares. +} +\newcommand{\copyrightNL}{ + Copyright {\copyright} \number\year~\Deltares\\ + Alle rechten voorbehouden. Niets uit deze uitgave mag worden verveelvoudigd in enige vorm door middel van druk, fotokopie, + microfilm of op welke andere wijze dan ook, zonder voorafgaande schriftelijke toestemming van de uitgever: Deltares. +} +\newcommand{\copyrightESP}{ + Copyright {\copyright} \number\year~\Deltares\\ + Todos los derechos reservados. Queda prohibida la reproducci\'on total o parcial, + ya sea de forma impresa, reprografiada, microfilmada o de cualquier otra forma, + salvo autorizaci\'on previa expresa por escrito del editor: Deltares. +} +% +%------------------------------------------------------------------------------ +% +% STATE PAGE +% +%------------------------------------------------------------------------------ +% +\long\def\LastPage{% + \cleardoublepage% + \pagestyle{empty}% + \newpage% + \phantom{m}% + \newpage% + \phantom{m}% + %\AddToShipoutPicture*{\BottomLastPage}% +} + +\if@dutch + \newcommand{\contactsalesandsupport}{ + \begin{tabular}[t]{@{}p{0.50\textwidth}p{0.50\textwidth}} + \begin{tabbing} + \textbf{Verkoop:} \\ + telefoon: \= +31\,88\,335\,81\,88 \\ + fax: \> +31\,88\,335\,81\,11 \\ + e-mail: \> software@deltares.nl \\ + www: \> https://www.deltares.nl/software + \end{tabbing} + % + & + % + \begin{tabbing} + \textbf{Ondersteuning:} \\ + telefoon: \= +31\,88\,335\,81\,00 \\ + fax: \> +31\,88\,335\,81\,11 \\ + e-mail: \> software.support@deltares.nl \\ + www: \> https://www.deltares.nl/software + \end{tabbing} + \end{tabular} + } +\else + \newcommand{\contactsalesandsupport}{ + \begin{tabular}[t]{@{}p{0.50\textwidth}p{0.50\textwidth}} + \begin{tabbing} + \textbf{For sales contact:} \\ + telephone: \= +31\,88\,335\,81\,88 \\ + fax: \> +31\,88\,335\,81\,11 \\ + e-mail: \> software@deltares.nl\\ + www: \> https://www.deltares.nl/software + \end{tabbing} + % + & + % + \begin{tabbing} + \textbf{For support contact:} \\ + telephone: \= +31\,88\,335\,81\,00 \\ + fax: \> +31\,88\,335\,81\,11 \\ + e-mail: \> software.support@deltares.nl\\ + www: \> https://www.deltares.nl/software + \end{tabbing} + \end{tabular} + } +\fi +\newcommand{\manualtitle}{% + \frontmatter + \pagenumbering{roman}% + \maketitle% + \pagestyle{empty}% + \textbf{\@title, \@manualtype} + + \vskip 1cm + \vfill\vfill\vfill + \if@dutch + \begin{tabular}{@{}p{0.50\textwidth}p{0.50\textwidth}} + \begin{tabbing} + \textbf{Gepubliceerd en gedrukt door:} \\ + Deltares\\ + Boussinesqweg 1\\ + 2629 HV Delft\\ + Postbus 177\\ + 2600 MH Delft\\ + Nederland + \end{tabbing} + & + \begin{tabbing} + \\ + telefoon: \= +31\,88\,335\,82\,73\\ + fax: \> +31\,88\,335\,85\,82\\ + e-mail: \> info@deltares.nl\\ + www: \> https://www.deltares.nl + \end{tabbing} + \end{tabular} + \else + \if@spanish + \begin{tabular}{@{}p{0.50\textwidth}p{0.50\textwidth}} + \begin{tabbing} + \textbf{Publicado e impreso por:} \\ + Deltares\\ + Boussinesqweg 1\\ + 2629 HV Delft\\ + buz\'on 177\\ + 2600 MH Delft\\ + Pa\'ises Bajos + \end{tabbing} + & + \begin{tabbing} + \\ + tel\'efono: \= +31\,88\,335\,82\,73\\ + fax: \> +31\,88\,335\,85\,82\\ + e-mail: \> info@deltares.nl\\ + www: \> https://www.deltares.nl + \end{tabbing} + \end{tabular} + \else + \begin{tabular}{@{}p{0.50\textwidth}p{0.50\textwidth}} + \begin{tabbing} + \textbf{Published and printed by:} \\ + Deltares\\ + Boussinesqweg 1\\ + 2629 HV Delft\\ + P.O.\ 177\\ + 2600 MH Delft\\ + The Netherlands + \end{tabbing} + & + \begin{tabbing} + \\ + telephone: \= +31\,88\,335\,82\,73\\ + fax: \> +31\,88\,335\,85\,82\\ + e-mail: \> info@deltares.nl\\ + www: \> https://www.deltares.nl + \end{tabbing} + \end{tabular} + \fi + \fi + + \contactsalesandsupport + %\vskip 10mm + %The screen pictures shown in this manual were produced during the development stages and may differ from the actual product + + \if@dutch + \copyrightNL + \else + \if@spanish + \copyrightESP + \else + \copyrightGB + \fi + \fi +% +% Print the signatures +% + \cleardoublepage% + \if@signature + \if@dutch + \signaturenl + \else + \signaturegb + \fi% end if@dutch + \else + \fi% end if@signature + + \pagestyle{frontmatterplain}% + \tableofcontents% + \conditionalLoF% Conditionally insert List of Figures + \conditionalLoT% Conditionally insert List of Tables + \printnomenclature% Conditionally insert List of Symbols, package: nomentbl + \mainmatter + + % At this point document title is known for sure. + % Now measure the width of title in page footers (later used in fancy page styles). + % When larger than max width, reduce it to max width. + % Result: parbox in footer has exactly right with, such that alignment and + % possible line break of title in footer is fully automatic. + \setlength{\maxfoottitlewidth}{125mm} + \settowidth{\foottitlewidth}{\headerfont \@title} + \ifthenelse{\lengthtest{\foottitlewidth > \maxfoottitlewidth}}{% + \setlength{\foottitlewidth}{\maxfoottitlewidth}} + + %\global\let\manualtitle\relax% +}% +%------------------------------------------------------------------------------ +% +% Change header and footer +% +\usepackage{fancyhdr} +\newcommand{\headerfont}{\selectfont} + +\pagestyle{fancy} +\renewcommand{\chaptermark}[1]{\markboth{#1}{}} + +% parbox width for title in footer: lengths are set in \manualtitle. +\newlength{\maxfoottitlewidth} +\newlength{\foottitlewidth} +% Used for title page +%\fancypagestyle{empty}{% + %\fancyhead{}% + %\fancyfoot{}% + %\fancyfoot[CO,CE]{\headerfont pagestyle: empty} +%} + +% Used for toc, lof, lot, preface (frontmatter) +\fancypagestyle{frontmatterplain}{% + \fancyhead{}% + \fancyhead[LO]{\headerfont } + \fancyhead[CO]{\headerfont } + \fancyhead[RO]{\headerfont \thechap} % chaptername + \fancyhead[RE]{\headerfont } + \fancyhead[CE]{\headerfont } + \fancyhead[LE]{\headerfont \@title, \@manualtype} + \fancyfoot{} + \fancyfoot[LO,RE]{\headerfont \Deltares} +% \fancyfoot[CO,CE]{\headerfont pagestyle: frontmatterplain} + \fancyfoot[RO,LE]{\headerfont \thepage} +} + +% Used for other pages +\fancypagestyle{headings}{% + \fancyhead{} + \fancyhead[LO]{\headerfont } + \fancyhead[CO]{\headerfont } + \fancyhead[RO]{\headerfont \thechap} % chaptername + \fancyhead[RE]{\headerfont } + \fancyhead[CE]{\headerfont } + \fancyhead[LE]{\headerfont \@title, \@manualtype} + \fancyfoot{} + \fancyfoot[LO,RE]{\headerfont \Deltares} +% \fancyfoot[CO,CE]{\headerfont pagestyle: headings} + \if@dutch + \fancyfoot[RO,LE]{\headerfont \thepage\ van \pageref*{LastPage}}% + \else + \fancyfoot[RO,LE]{\headerfont \thepage\ of \pageref*{LastPage}}% + \fi +} + +% Used for first page of chapter +\fancypagestyle{plainChapter}{% + \renewcommand{\headrulewidth}{0pt} + \fancyhead{}% + \fancyfoot{}% + \fancyfoot[LO,RE]{\headerfont \Deltares} +% \fancyfoot[CO,CE]{\headerfont \thepage}%pagestyle: plainChapter} + \if@dutch + \fancyfoot[RO,LE]{\headerfont \thepage\ van \pageref*{LastPage}}% + \else + \fancyfoot[RO,LE]{\headerfont \thepage\ of \pageref*{LastPage}}% + \fi +} + +% Used for first page of part +\fancypagestyle{plainPart}{% + \AddToShipoutPicture*{\BackgroundPicPart} + \renewcommand{\headrulewidth}{0pt} + \fancyhead{}% + \fancyfoot{}% +% \fancyfoot[LO,RE]{\headerfont \Deltares} +% \fancyfoot[CO,CE]{\headerfont pagestyle: plainPart} +% \fancyfoot[RO,LE]{\headerfont \thepage}% +} + +\addtocounter{secnumdepth}{1} +\setlength{\parskip}{\baselineskip} +\setlength{\parindent}{0pt} +\setlength{\parsep}{1pt} +\setlength{\partopsep}{1pt} +%\setlength{\rightskip}{0pt plus 2cm} % Niet rechts uitlijnen tekst +%\setlength{\@rightskip}{0pt plus 2cm} % Niet rechts uitlijnen lists + +%------------------------------------------------------------------------------ +% +% To change the caption of tables and figures. +% Format is defautl or `hang' wich aligns caption to the right of the figure statement +\captionsetup{format=hang,margin=0.9cm,font=small,labelfont={sl,bf},textfont=sl} +% +%------------------------------------------------------------------------------ +% +% Define a more advanced remark environment that writes Remark if there is only +% one item and that writes Remarks if there are multiple items. +% +\usepackage{ifthen} + +% +\newcounter{n_sp_blocks} +\newcounter{n_sp_items} +\newenvironment{singleplural}[2]% + {\addtocounter{n_sp_blocks}{1}% + \ifthenelse{\equal{a\ref{sp_block\arabic{n_sp_blocks}}}{a1}}% + {\textbf{#1:}}% + {\textbf{#2:}}% + \begin{list}{\labelitemi}{% + \setlength{\parskip}{0pt}% + \setlength{\parsep}{0pt}% + \setlength{\topsep}{0pt}% + \setlength{\itemsep}{0pt}% + \usecounter{n_sp_items}% + }}% + {\label{sp_block\arabic{n_sp_blocks}}\end{list}} +% +\if@dutch + \newenvironment{Remark}% + {\marginnote{{\includegraphics[height=1.5\baselineskip]{pictures/margin_remark.pdf}}}[1.50ex]% + \begin{singleplural}{Opmerking}{Opmerkingen}} + {\end{singleplural}} +\else + \newenvironment{Remark}% + {\marginnote{{\includegraphics[height=1.5\baselineskip]{pictures/margin_remark.pdf}}}[1.50ex]% + \begin{singleplural}{Remark}{Remarks}} + {\end{singleplural}} +\fi +% +\if@dutch + \newenvironment{Restriction}% + {\marginnote{{\includegraphics[height=1.5\baselineskip]{pictures/margin_restriction.pdf}}}[1.50ex]% + \begin{singleplural}{Restrictie}{Restricties}} + {\end{singleplural}} +\else + \newenvironment{Restriction}% + {\marginnote{{\includegraphics[height=1.5\baselineskip]{pictures/margin_restriction.pdf}}}[1.50ex]% + \begin{singleplural}{Restriction}{Restrictions}} + {\end{singleplural}} +\fi +% +\if@dutch + \newenvironment{Warning}% + {\marginnote{{\includegraphics[height=1.5\baselineskip]{pictures/margin_warning.pdf}}}[1.25ex]% + \begin{singleplural}{Waarschuwing}{Waarschuwingen}} + {\end{singleplural}} +\else + \newenvironment{Warning}% + {\marginnote{{\includegraphics[height=1.5\baselineskip]{pictures/margin_warning.pdf}}}[1.25ex]% + \begin{singleplural}{Warning}{Warnings}} + {\end{singleplural}} +\fi +% +\newcommand{\Note}% +{% + \textbf{Note:\ } + \marginnote{ {\includegraphics[height=1.5\baselineskip]{pictures/margin_note.pdf}} }[-0.75ex]% +} +% +\newcommand{\Tip}% +{% + \textbf{Tip:\ }% + \marginnote[ {\includegraphics[height=1.5\baselineskip]{pictures/margin_tip_left.pdf}} ]% + { {\includegraphics[height=1.5\baselineskip]{pictures/margin_tip_right.pdf}} }[-0.75ex]% +} +% todo macro: usage of package marginnote +\renewcommand*{\raggedleftmarginnote}{\raggedleft} +\renewcommand*{\raggedrightmarginnote}{\raggedright} +\newcommand{\todo}[1]{ + {\color[rgb]{0,0.2,0.5}\textbf{TODO(??):} }% + \protect\marginnote{\textbf{TODO}}% + {\color[rgb]{0,0.2,0.5}\slshape #1}% +} +% +\RecustomVerbatimEnvironment + {Verbatim}{Verbatim} + {fontsize=\footnotesize} + +% +% Nomenclature table +\if@dutch + \def\nomname{Lijst van symbolen} + \def\nomAname{Latijnse letters}% + \def\nomGname{Griekse letters}% + \def\nomXname{Superscripts}% + \def\nomZname{Subscripts}% +\else + \def\nomname{List of Symbols} + \def\nomAname{Latin Letters}% + \def\nomGname{Greek Letters}% + \def\nomXname{Superscripts}% + \def\nomZname{Subscripts}% +\fi +% +%------------------------------------------------------------------------------ +% Bring items closer together in list environments +% +\let\orig@Itemize =\itemize +\let\orig@Enumerate =\enumerate +\let\orig@Description =\description +% Zero the vertical spacing parameters +\def\Nospacing{\itemsep=0pt\topsep=0pt\partopsep=0pt\parskip=0pt\parsep=0pt} +\renewenvironment{itemize}{\orig@Itemize\Nospacing}{\endlist} +\renewenvironment{enumerate}{\orig@Enumerate\Nospacing}{\endlist} +\renewenvironment{description}{\orig@Description\Nospacing}{\endlist} + +\renewcommand\labelitemi{$\boldsymbol\diamond$} +\renewcommand\labelitemii{\rotatebox{45}{$\boldsymbol\diamond$}} % +\renewcommand\labelitemiii{$\boldsymbol\circ$} +\renewcommand\labelitemiv{$\boldsymbol\triangleright$} + +\renewcommand{\labelenumi}{\arabic{enumi}} +\renewcommand{\labelenumii}{\arabic{enumi}.\arabic{enumii}} +\renewcommand{\labelenumiii}{\arabic{enumi}.\arabic{enumii}.\arabic{enumiii}} +\renewcommand{\labelenumiv}{\arabic{enumi}.\arabic{enumii}.\arabic{enumiii}.\arabic{enumiv}} + +% +%------------------------------------------------------------------------------ + +\newenvironment{guilist}% + {\begin{list}{}% + {% + \renewcommand{\makelabel}[1]% + {\raisebox{0pt}[1ex][0pt]{\makebox[\labelwidth][l]% + {\parbox[t]{\labelwidth}{\raggedright\hspace{0pt}##1}}}}% + \setlength{\parskip}{\baselineskip/2}% + \setlength{\labelwidth}{3.7cm}% + \setlength{\leftmargin}{\labelwidth+\labelsep}% + \setlength{\topsep}{0pt}% + \setlength{\topsep}{0pt}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{0pt}% + }% + }% + {\end{list}} + +\if@dutch + \newenvironment{domain} % Added more spacing around the text in the header, 19/11/2008 RMC Spiteri + {% + \small\begin{tabular}{|p{4.4cm}|p{2.2cm}|p{2.2cm}|p{2.2cm}|p{\textwidth-63pt-11.0cm}|} + \multicolumn{5}{@{}l}{\STRUT \textbf{Domein:}} \\ [1ex] \hline \STRUT + \textbf{Parameter} & \textbf{Onder limiet} & \textbf{Boven limiet} & \textbf{Default} & \textbf{Eenheid} \\[1ex] \hline + } + {\end{tabular}} +\else + \newenvironment{domain} % Added more spacing around the text in the header, 19/11/2008 RMC Spiteri + {% + \small\begin{tabular}{|p{4.4cm}|p{2.2cm}|p{2.2cm}|p{2.2cm}|p{\textwidth-63pt-11.0cm}|} + \multicolumn{5}{@{}l}{\STRUT \textbf{Domain:}} \\ [1ex] \hline \STRUT + \textbf{Parameter} & \textbf{Lower limit} & \textbf{Upper limit} & \textbf{Default} & \textbf{Unit} \\[1ex] \hline + } + {\end{tabular}} +\fi + +\newenvironment{action}% + {\begin{list}{}{% + \renewcommand{\makelabel}[1]{\includegraphics[height=0.5\baselineskip]{pictures/action_arrow.pdf}\hfill\varlistcolon}% + \setlength{\labelwidth}{1em+1pt}% Changed to 3.7cm, 19/11/2008 RMC Spiteri + \setlength{\leftmargin}{\labelwidth+\labelsep}% + \setlength{\parskip}{\baselineskip/2}% + \setlength{\topsep}{0pt}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{0pt}}} + {\end{list}} +% +% definition of varlist environment for listing +% variables and their meaning after a formula +% +\newcommand{\varlistcolon}{} % originally : +\newenvironment{varlist}% + {\begin{list}{}{% + \renewcommand{\makelabel}[1]{\quad{##1}\hfill\varlistcolon}% + \setlength{\labelwidth}{3.7cm}% Changed to 3.7cm, 19/11/2008 RMC Spiteri + \setlength{\leftmargin}{\labelwidth+\labelsep}% + \setlength{\parskip}{\baselineskip/2}% + \setlength{\topsep}{0pt}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{0pt}}} + {\end{list}} + +%------------------------------------------------------------------------------ + +\newenvironment{symbollist}% + {\begin{list}{}{% + \renewcommand{\makelabel}[1]{\quad{##1}\hfill\varlistcolon}% + \setlength{\labelwidth}{2.0cm} + \setlength{\leftmargin}{\labelwidth+\labelsep}% + \setlength{\parskip}{\baselineskip/2}% + \setlength{\topsep}{0pt}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{0pt}}} + {\end{list}} + +%------------------------------------------------------------------------------ + +\newenvironment{options}% + {\underline{Options:} + \begin{list}{}% + {% + \renewcommand{\makelabel}[1]% + {\raisebox{0pt}[1ex][0pt]{\makebox[\labelwidth][l]% + {\parbox[t]{\labelwidth}{\raggedright\hspace{0pt}##1}}}}% + \setlength{\labelwidth}{3.7cm}% + \setlength{\leftmargin}{\labelwidth+\labelsep}% + \setlength{\parskip}{\baselineskip/2}% + \setlength{\topsep}{0pt}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{0pt} + }% + }% + {\end{list}} + +%------------------------------------------------------------------------------ + +\def\nonumchapter#1{% + \chapter*{#1}% + \addcontentsline{toc}{chapter}{#1}% + \markboth{#1}{}} + +%------------------------------------------------------------------------------ +\newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}\cleardoublepage}} +\newcommand{\STRUT}{\rule{0in}{3ex}} + + +\newcommand{\WL}{{WL\,$|$\,Delft Hydraulics}\xspace} +\newcommand{\Deltares}{Deltares\xspace} +\newcommand{\degr}{\ensuremath{^\circ}} +\newcommand{\tenlog}{ \ensuremath{\ {}^{10}\!\log} } +\newcommand{\twolog}{ \ensuremath{\ {}^{2}\!\log} } +\newcommand{\xml}{xml\xspace} + +\newcommand{\window}[1]{\textbf{#1}} +\newcommand{\menu}[1]{\emph{#1}} +\newcommand{\button}[1]{\emph{#1}} +\newcommand{\file}[1]{$<${#1}$>$} +\newcommand{\dir}[1]{$<${#1}$>$} +\newcommand{\ginput}[1]{``#1''} +\newcommand{\command}[1]{{\normalfont\ttfamily #1}} +\newcommand{\block}[1]{\textbf{\rmfamily #1}} +\newcommand{\keyw}[1]{{\normalfont\ttfamily #1}} +\newcommand{\unitbrackets}[1]{[#1]} +\newcommand{\ext}[1]{$<$#1$>$} +\newcommand{\key}[1]{\texttt{#1}} +\newcommand{\function}[1]{\emph{#1}} + +\DeclareRobustCommand\dotp{\mathpalette\dotp@{.5}} % bullet for the dot product +\newcommand\dotp@[2]{\mathbin{\vcenter{\hbox{\scalebox{#2}{$\m@th#1\bullet$}}}}} +\newcommand{\ssquare}{\stackrel{\scriptscriptstyle\square}{{}}} % small square for itemize list + +\newcommand{\option}[1]{\vspace{0.5cm}\underline{#1}} % Emphasize an option, mainly used in WAQ TRM + +%% Referencing +\let\origtheequation\theequation +\def\tagform@#1{\maketag@@@{\ignorespaces#1\unskip\@@italiccorr}} +\renewcommand{\theequation}{(\origtheequation)} +\newcommand*\Autoref[1]{% First letter is a capital, also from macro \Autoref + \begingroup + \if@dutch + \def\appendixautorefname{Appendix}% + \def\chapterautorefname{Hoofdstuk}% + \def\equationautorefname{Vergelijking}% + \def\figureautorefname{Figuur}% + \def\footnoteautorefname{Voetnoot}% + \def\itemautorefname{Item}% + \def\pageautorefname{Bladzijde}% + \def\paragraphautorefname{Paragraaf}% + \def\partautorefname{Deel}% + \def\sectionautorefname{Paragraaf}% + \def\subparagraphautorefname{Paragraaf}% + \def\subsectionautorefname{Paragraaf}% + \def\subsubsectionautorefname{Paragraaf}% + \def\tableautorefname{Tabel}% + \def\theoremautorefname{Theorema}% + \else + \def\appendixautorefname{Appendix}% + \def\chapterautorefname{Chapter}% + \def\equationautorefname{Equation}% + \def\figureautorefname{Figure}% + \def\footnoteautorefname{Footnote}% + \def\itemautorefname{Item}% + \def\pageautorefname{Page}% + \def\paragraphautorefname{Section}% + \def\partautorefname{Part}% + \def\sectionautorefname{Section}% + \def\subparagraphautorefname{Section}% + \def\subsectionautorefname{Section}% + \def\subsubsectionautorefname{Section}% + \def\tableautorefname{Table}% + \def\theoremautorefname{Theorem}% + \fi + % ... + \autoref{#1}% + \endgroup% +} + +\if@dutch % First letter is a lower case, also from macro \autoref + \def\appendixautorefname{appendix}% + \def\chapterautorefname{hoofdstuk}% + \def\equationautorefname{vergelijking}% + \def\figureautorefname{figuur}% + \def\footnoteautorefname{voetnoot}% + \def\itemautorefname{item}% + \def\pageautorefname{bladzijde}% + \def\paragraphautorefname{paragraaf}% + \def\partautorefname{deel}% + \def\sectionautorefname{paragraaf}% + \def\subparagraphautorefname{paragraaf}% + \def\subsectionautorefname{paragraaf}% + \def\subsubsectionautorefname{paragraaf}% + \def\tableautorefname{tabel}% + \def\theoremautorefname{theorema}% +\else + \addto\extrasenglish{ + \def\appendixautorefname{Appendix}% + \def\chapterautorefname{chapter}% + \def\equationautorefname{Equation}% + \def\figureautorefname{Figure}% + \def\footnoteautorefname{footnote}% + \def\itemautorefname{item}% + \def\pageautorefname{page}% + \def\paragraphautorefname{section}% + \def\partautorefname{Part}% + \def\sectionautorefname{section}% + \def\subparagraphautorefname{section}% + \def\subsectionautorefname{section}% + \def\subsubsectionautorefname{section}% + \def\tableautorefname{Table}% + \def\theoremautorefname{Theorem}% + } +\fi + +\newcommand{\Cref}[1]{\autoref{#1}} +\newcommand{\Sref}[1]{\autoref{#1}} +\newcommand{\Fref}[1]{\autoref{#1}} +\if@dutch + \newcommand{\Frefs}[2]{Figuren~\ref{#1} en \ref{#2}} + \newcommand{\Freft}[2]{Figuren~\ref{#1} tot \ref{#2}} +\else + \newcommand{\Frefs}[2]{Figures~\ref{#1} and \ref{#2}} + \newcommand{\Freft}[2]{Figures~\ref{#1} to \ref{#2}} +\fi +\newcommand{\Aref}[1]{\autoref{#1}} +\newcommand{\Apref}[1]{\autoref{#1}} +\newcommand{\Tref}[1]{\autoref{#1}} +\newcommand{\Eref}[1]{\autoref{#1}} + + +\hyphenation{bathy-metry fa-vour-able} + +\def\execute{% + \begingroup% + \catcode`\%=12% + \catcode`\\=12% + \executeaux}% + \def\executeaux#1{\immediate\write18{#1}% + \endgroup% +} +%------------------------------------------------------------------------------ +% +% PART +% +% Copied from report.cls, but pagestyle now depends on front/mainmatter: +\newcommand\BackgroundPicPart{} +\usepackage{eso-pic} +\renewcommand\chapter{\if@openright\cleardoublepage\else\clearpage\fi + \if@mainmatter\thispagestyle{plainChapter}\else\thispagestyle{frontmatterplain}\fi% + \global\@topnum\z@ + \@afterindentfalse + \secdef\@chapter\@schapter + } +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% + \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + {\centering + \interlinepenalty \@M + \normalfont + \thispagestyle{plainPart} + \ifnum \c@secnumdepth >-2\relax + \leavevmode\HUGE\bfseries\raggedright #2 + \par + \vskip 20\p@ + \fi + \par}% + \renewcommand{\partname}[1]{#1} + \@endpart} +%------------------------------------------------------------------------------ +% +% CHAPTER redefinition Hoofdstuk nummmer en titel +% +\newcommand\BackgroundPicChapter{} +\def\@makechapterhead#1{% + \AddToShipoutPicture*{\BackgroundPicChapter} % + \vspace{0\baselineskip}% + {\parindent \z@% + \leavevmode\Large\bfseries\raggedright% + \llap{\thechapter\hspace{4.5mm}}#1% + \par\nobreak + \vskip 0\baselineskip% + } +} +\def\@makeschapterhead#1{% + \AddToShipoutPicture*{\BackgroundPicChapter} % + \vspace{0\baselineskip}% + {\parindent \z@ + \leavevmode\Large\bfseries\raggedright% + \llap{}#1 + \par\nobreak + \vskip 0\baselineskip% + } +} +%------------------------------------------------------------------------------ +% +% SECTION redefinition +% +\def\section{\@ifstar\unnumberedsection\numberedsection} +\def\numberedsection{\@ifnextchar[%] + \numberedsectionwithtwoarguments\numberedsectionwithoneargument} +\def\unnumberedsection{\@ifnextchar[%] + \unnumberedsectionwithtwoarguments\unnumberedsectionwithoneargument} +\def\numberedsectionwithoneargument#1{\numberedsectionwithtwoarguments[#1]{#1}} +\def\unnumberedsectionwithoneargument#1{\unnumberedsectionwithtwoarguments[#1]{#1}} + +\def\numberedsectionwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak + \refstepcounter{section}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\raggedright + \llap{\thesection\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak + \addcontentsline{toc}{section}{% + \protect\numberline{\thesection}% + #1}% + } +\def\unnumberedsectionwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak +% \refstepcounter{section}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\raggedright +% \llap{\thesection\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak +% \addcontentsline{toc}{section}{% +% \protect\numberline{\thesection}% +% #1}% + } +%------------------------------------------------------------------------------ +% +% SUBSECTION redefinition +% +\def\subsection{\@ifstar\unnumberedsubsection\numberedsubsection} +\def\numberedsubsection{\@ifnextchar[%] + \numberedsubsectionwithtwoarguments\numberedsubsectionwithoneargument} +\def\unnumberedsubsection{\@ifnextchar[%] + \unnumberedsubsectionwithtwoarguments\unnumberedsubsectionwithoneargument} +\def\numberedsubsectionwithoneargument#1{\numberedsubsectionwithtwoarguments[#1]{#1}} +\def\unnumberedsubsectionwithoneargument#1{\unnumberedsubsectionwithtwoarguments[#1]{#1}} + +\def\numberedsubsectionwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak + \refstepcounter{subsection}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\raggedright + \llap{\thesubsection\hspace{4.5mm}}% + #2 +\par + \endgroup + \vskip -0.5\parskip\nobreak + \addcontentsline{toc}{subsection}{% + \protect\numberline{\thesubsection}% + #1}% + } +\def\unnumberedsubsectionwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak +% \refstepcounter{subsection}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\raggedright +% \llap{\thesubsection\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak +% \addcontentsline{toc}{subsection}{% +% \protect\numberline{\thesubsection}% +% #1}% + } +%------------------------------------------------------------------------------ +% +% SUBSUBSECTION redefinition +% +\def\subsubsection{\@ifstar\unnumberedsubsubsection\numberedsubsubsection} +\def\numberedsubsubsection{\@ifnextchar[%] + \numberedsubsubsectionwithtwoarguments\numberedsubsubsectionwithoneargument} +\def\unnumberedsubsubsection{\@ifnextchar[%] + \unnumberedsubsubsectionwithtwoarguments\unnumberedsubsubsectionwithoneargument} +\def\numberedsubsubsectionwithoneargument#1{\numberedsubsubsectionwithtwoarguments[#1]{#1}} +\def\unnumberedsubsubsectionwithoneargument#1{\unnumberedsubsubsectionwithtwoarguments[#1]{#1}} + +\def\numberedsubsubsectionwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak + \refstepcounter{subsubsection}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\raggedright + \llap{\thesubsubsection\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak + \addcontentsline{toc}{subsubsection}{% + \protect\numberline{\thesubsubsection}% + #1}% + } +\def\unnumberedsubsubsectionwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak +% \refstepcounter{subsubsection}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\raggedright +% \llap{\thesubsubsection\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak +% \addcontentsline{toc}{subsubsection}{% +% \protect\numberline{\thesubsubsection}% +% #1}% + } +%------------------------------------------------------------------------------ +% +% PARAGRAPH redefinition +% +\def\paragraph{\@ifstar\unnumberedparagraph\numberedparagraph} +\def\numberedparagraph{\@ifnextchar[%] + \numberedparagraphwithtwoarguments\numberedparagraphwithoneargument} +\def\unnumberedparagraph{\@ifnextchar[%] + \unnumberedparagraphwithtwoarguments\unnumberedparagraphwithoneargument} +\def\numberedparagraphwithoneargument#1{\numberedparagraphwithtwoarguments[#1]{#1}} +\def\unnumberedparagraphwithoneargument#1{\unnumberedparagraphwithtwoarguments[#1]{#1}} + +\def\numberedparagraphwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak + \refstepcounter{paragraph}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\raggedright + \llap{\theparagraph\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak + \addcontentsline{toc}{paragraph}{% + \protect\numberline{\theparagraph}% + #1}% + } +\def\unnumberedparagraphwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak +% \refstepcounter{paragraph}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\raggedright +% \llap{\theparagraph\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak +% \addcontentsline{toc}{paragraph}{% +% \protect\numberline{\theparagraph}% +% #1}% + } +%------------------------------------------------------------------------------ +% +% SUBPARAGRAPH redefinition +% +\def\subparagraph{\@ifstar\unnumberedsubparagraph\numberedsubparagraph} +\def\numberedsubparagraph{\@ifnextchar[%] + \numberedsubparagraphwithtwoarguments\numberedsubparagraphwithoneargument} +\def\unnumberedsubparagraph{\@ifnextchar[%] + \unnumberedsubparagraphwithtwoarguments\unnumberedsubparagraphwithoneargument} +\def\numberedsubparagraphwithoneargument#1{\numberedsubparagraphwithtwoarguments[#1]{#1}} +\def\unnumberedsubparagraphwithoneargument#1{\unnumberedsubparagraphwithtwoarguments[#1]{#1}} + +\def\numberedsubparagraphwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak + \refstepcounter{subparagraph}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\itshape\raggedright + \llap{\thesubparagraph\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak + \addcontentsline{toc}{subparagraph}{% + \protect\numberline{\thesubparagraph}% + #1}% + } +\def\unnumberedsubparagraphwithtwoarguments[#1]#2{% + \def\@currentlabelname{#1} + \ifhmode\par\fi + \removelastskip + \vskip -0.5\baselineskip\nopagebreak +% \refstepcounter{subparagraph}% + \noindent + \begingroup + % Taken from package needspaces + \setlength{\dimen@}{3\baselineskip}% + \vskip\z@\@plus\dimen@ + \penalty -100\vskip\z@\@plus -\dimen@ + \vskip\dimen@ + \penalty 9999% + \vskip -\dimen@ + \vskip\z@skip % hide the previous \vskip from \addvspace + % end needspaces + \leavevmode\normalsize\bfseries\itshape\raggedright +% \llap{\thesubparagraph\hspace{4.5mm}}% + #2 + \par + \endgroup + \vskip -0.5\parskip\nobreak +% \addcontentsline{toc}{subparagraph}{% +% \protect\numberline{\thesubparagraph}% +% #1}% + } + +%------------------------------------------------------------------------------ +% +% INDEX +% +\usepackage{makeidx} +\usepackage[totoc=true]{idxlayout} +%------------------------------------------------------------------------------ +% +%\def\promille{\leavevmode\kern-.05em +%\raise.5ex\hbox{\the\scriptfont0 0}\kern-.15em/\kern-.15em +%\lower.25ex\hbox{\the\scriptfont0 00}} + +\newcommand{\promille}{% + \relax\ifmmode\promillezeichen + \else\leavevmode\(\mathsurround=0pt\promillezeichen\)\fi} +\newcommand{\promillezeichen}{% + \kern-.05em% + \raise.5ex\hbox{\the\scriptfont0 0}% + \kern-.15em/\kern-.15em% + \lower.25ex\hbox{\the\scriptfont0 00}} + +%% Longtable improvement +% \nobreakhline is a \hline in a longtable that disallows a page break after it. +% From: http://tex.stackexchange.com/questions/6350/how-to-disable-pagebreak-on-hline-in-longtable +\def\nobreakhline{% + \noalign{\ifnum0=`}\fi + \penalty\@M + \futurelet\@let@token\LT@@nobreakhline% +} +\def\LT@@nobreakhline{% + \ifx\@let@token\hline + \global\let\@gtempa\@gobble + \gdef\LT@sep{\penalty\@M\vskip\doublerulesep}% <-- change here + \else + \global\let\@gtempa\@empty + \gdef\LT@sep{\penalty\@M\vskip-\arrayrulewidth}% <-- change here + \fi + \ifnum0=`{\fi}% + \multispan\LT@cols + \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr + \noalign{\LT@sep}% + \multispan\LT@cols + \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr + \noalign{\penalty\@M}% + \@gtempa +} + +%------------------------------------------------------------------------------ +% footnote references +% +\newcommand{\footnoteref}[1]{% +% requires a label to be present in the footnote to be referenced! +\ltx@ifpackageloaded{hyperref}{% hyperref package loaded + \ifHy@hyperfootnotes% option hyperfootnotes=true + \hbox{\hyperref[#1]{% + % once upon a time this was not "#1" but "\footnote@reference", + % but somewhere something changed at some time + \@textsuperscript {\normalfont \ref*{#1}}}}% + \else% option hyperfootnotes=false + \hbox{\@textsuperscript {\normalfont \ref*{#1}}}% + \fi% +}{% hyperref package not loaded + \hbox{\@textsuperscript {\normalfont \ref{#1}}}% + }% +} +%------------------------------------------------------------------------------ + +\newcommand{\diff}[3][1]{\ensuremath{\frac{d \ifthenelse{\equal{#1}{1}}{}{^#1} {#2}}{d {#3} \ifthenelse{\equal{#1}{1}}{}{^#1}}}} +\newcommand{\pdiff}[3][1]{\ensuremath{\frac{\partial \ifthenelse{\equal{#1}{1}}{}{^#1} {#2}}{\partial {#3} \ifthenelse{\equal{#1}{1}}{}{^#1}}}} + +\newcommand{\perscomm}[1]{\citetext{#1, pers.\ comm.}} +\newcommand{\deltarestitle}{\manualtitle}% + +\if@dbiblatex + \usepackage[backend=bibtex, style=deltares_authoryear, maxcitenames=2, maxbibnames=10]{biblatex} + \newcommand{\printrefsegment}{\printbibliography[segment=\therefsegment, heading=subbibheading]} + \newcommand{\printallbibliography}{\printbibliography[heading=bibintoc]} + \if@dutch + \DefineBibliographyStrings{dutch}{% + bibliography = {Referenties} + } + \defbibheading{subbibheading}{ + \subparagraph*{Referenties} % for \Autoref{refsegment:\therefsection\therefsegment}} + } + \DeclareFieldFormat{urldate}{% + (Benaderd % + \thefield{urlday} \addspace% + \mkbibmonth{\thefield{urlmonth}}\addspace% + \thefield{urlyear}\isdot)} + \else % i.e. English + \DefineBibliographyStrings{english}{% + bibliography = {References} + } + \defbibheading{subbibheading}{ + \subparagraph*{References} % for \Autoref{refsegment:\therefsection\therefsegment}} + } + \DeclareFieldFormat{urldate}{% + (Accessed % + \thefield{urlday} \addspace% + \mkbibmonth{\thefield{urlmonth}}\addspace% + \thefield{urlyear}\isdot)} + \fi + \setlength\bibitemsep{0.5\baselineskip} +\else + \usepackage{natbib} + \bibpunct[, ]{(}{)}{;}{a}{,}{,} + \renewcommand\bibsection{} + \if@dutch + \bibliographystyle{deltares_chicago_like_dutch} + \else + \if@spanish + \bibliographystyle{deltares_chicago_like_spanish} + \else + \bibliographystyle{deltares_chicago_like} + \fi + \fi + %\usepackage{chapterbib} +\fi + +% +% Nomenclature; run makeindex with appropriate style file +% +\IfFileExists{./\jobname.nlo}{ + \if@dutch + \execute{makeindex -q \jobname.nlo -s deltares_nomentbl_nl.ist -o \jobname.nls} + \else + \execute{makeindex -q \jobname.nlo -s deltares_nomentbl.ist -o \jobname.nls} + \fi +}{} + +\def\@@nomenclature[#1]#2#3#4{\endgroup\@esphack} +\def\@@@nomenclature[#1]#2#3#4{% +\def\@tempa{#2}\def\@tempb{#3}% +\protected@write\@nomenclaturefile{}% +{\string\nomenclatureentry{#1\nom@verb\@tempa @{\nom@verb\@tempa}&% +\begingroup\nom@verb\@tempb\endgroup &\begingroup#4\endgroup&% +\begingroup\protect\nompageref}{0}% nompageref==0, so all entries of the page number are the same, needed to skip double entries +}% +\endgroup +\@esphack} + + +\makenomenclature + +\makeatother + diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/CreatePointProcedure.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/CreatePointProcedure.png new file mode 100644 index 000000000000..2d3ab814b7f1 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/CreatePointProcedure.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/GIDMainWindow.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/GIDMainWindow.png new file mode 100644 index 000000000000..1f3ec7c6690f Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/GIDMainWindow.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/acceptChange.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/acceptChange.png new file mode 100644 index 000000000000..09701dc95ccf Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/acceptChange.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/artifactsIcon.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/artifactsIcon.png new file mode 100644 index 000000000000..227f6740b754 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/artifactsIcon.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/assignBoundaryConditionBox.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/assignBoundaryConditionBox.png new file mode 100644 index 000000000000..772a917f1135 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/assignBoundaryConditionBox.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/assignToLine.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/assignToLine.png new file mode 100644 index 000000000000..81c048f4f4cc Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/assignToLine.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/assignToSurface.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/assignToSurface.png new file mode 100644 index 000000000000..5691865f9641 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/assignToSurface.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/boundaryConditionsWindow.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/boundaryConditionsWindow.png new file mode 100644 index 000000000000..11f594641f3f Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/boundaryConditionsWindow.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/clayMaterialWindowTut1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/clayMaterialWindowTut1.png new file mode 100644 index 000000000000..3577a9944ee1 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/clayMaterialWindowTut1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/contourFillIcon.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/contourFillIcon.png new file mode 100644 index 000000000000..1076da3fb486 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/contourFillIcon.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createArc.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/createArc.PNG new file mode 100644 index 000000000000..1b6e2234a6f1 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createArc.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createCurve.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/createCurve.PNG new file mode 100644 index 000000000000..1b6e2234a6f1 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createCurve.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createLine.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/createLine.PNG new file mode 100644 index 000000000000..9163a12871f3 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createLine.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createLines.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/createLines.PNG new file mode 100644 index 000000000000..8fa60e3d74d4 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createLines.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createNewGroup.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/createNewGroup.png new file mode 100644 index 000000000000..1467a291b4dc Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createNewGroup.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createNurbsLine.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/createNurbsLine.PNG new file mode 100644 index 000000000000..7acf3c395b7a Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createNurbsLine.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createNurbsSurface.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/createNurbsSurface.PNG new file mode 100644 index 000000000000..59dc535a0185 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createNurbsSurface.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createObject.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/createObject.PNG new file mode 100644 index 000000000000..fc678500ff82 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createObject.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/createVolume.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/createVolume.PNG new file mode 100644 index 000000000000..ed8ff7e806ae Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/createVolume.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/deleteAllButton.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/deleteAllButton.png new file mode 100644 index 000000000000..149d6f1a6731 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/deleteAllButton.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/deleteButton.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/deleteButton.png new file mode 100644 index 000000000000..f212ceb26833 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/deleteButton.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/dikeLevelTut1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/dikeLevelTut1.png new file mode 100644 index 000000000000..6c84868917b6 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/dikeLevelTut1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/dikeMaterialWindowTut1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/dikeMaterialWindowTut1.png new file mode 100644 index 000000000000..ac2a43502b3a Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/dikeMaterialWindowTut1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/dirichletConstraintsWindow.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/dirichletConstraintsWindow.png new file mode 100644 index 000000000000..73ed97d6bb2d Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/dirichletConstraintsWindow.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineAtIntersectLine.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineAtIntersectLine.PNG new file mode 100644 index 000000000000..fbddeff8bf29 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineAtIntersectLine.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineNearPoint.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineNearPoint.PNG new file mode 100644 index 000000000000..b22776d81598 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineNearPoint.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineNrDiv.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineNrDiv.PNG new file mode 100644 index 000000000000..bfce3a4ab726 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/divideLineNrDiv.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/divideSurfaceInNParts.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/divideSurfaceInNParts.PNG new file mode 100644 index 000000000000..797b490880ff Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/divideSurfaceInNParts.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/geometryTut1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/geometryTut1.png new file mode 100644 index 000000000000..f7ed8c969bb6 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/geometryTut1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/intersectMultipleSurfaces.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/intersectMultipleSurfaces.PNG new file mode 100644 index 000000000000..37ce99e6e6a7 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/intersectMultipleSurfaces.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/intersectSurfaceWithLines.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/intersectSurfaceWithLines.PNG new file mode 100644 index 000000000000..34942db7575c Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/intersectSurfaceWithLines.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/layersButton.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/layersButton.PNG new file mode 100644 index 000000000000..38bc655f16b3 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/layersButton.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/materialsWindow.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/materialsWindow.png new file mode 100644 index 000000000000..fd58192c9b2a Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/materialsWindow.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/movePoint.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/movePoint.PNG new file mode 100644 index 000000000000..f7991001a9c5 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/movePoint.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/newMaterial.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/newMaterial.PNG new file mode 100644 index 000000000000..1f74f880e111 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/newMaterial.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/outlinesTutorial1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/outlinesTutorial1.png new file mode 100644 index 000000000000..bec3c7cf6031 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/outlinesTutorial1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/rename.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/rename.PNG new file mode 100644 index 000000000000..20ce8f0417e3 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/rename.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/resultsTutorial1Part1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/resultsTutorial1Part1.png new file mode 100644 index 000000000000..7f756e664693 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/resultsTutorial1Part1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/riverLevelTut1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/riverLevelTut1.png new file mode 100644 index 000000000000..cefe4eda6d8d Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/riverLevelTut1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/riverLoadTut1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/riverLoadTut1.png new file mode 100644 index 000000000000..93b44b73ebd1 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/riverLoadTut1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/sandMaterialWindowTut1.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/sandMaterialWindowTut1.png new file mode 100644 index 000000000000..7ee5eaa463c1 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/sandMaterialWindowTut1.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/splitSurfaceFromPathOfLines.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/splitSurfaceFromPathOfLines.PNG new file mode 100644 index 000000000000..bcc20eaf403f Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/splitSurfaceFromPathOfLines.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/togglePostProcess.png b/applications/GeoMechanicsApplication/documents/tutorials/figures/togglePostProcess.png new file mode 100644 index 000000000000..5fd0e180dd05 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/togglePostProcess.png differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/figures/unassignGroup.PNG b/applications/GeoMechanicsApplication/documents/tutorials/figures/unassignGroup.PNG new file mode 100644 index 000000000000..c46ee8b28da0 Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/figures/unassignGroup.PNG differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/kratos_doxyfile b/applications/GeoMechanicsApplication/documents/tutorials/kratos_doxyfile new file mode 100644 index 000000000000..6957e64b8d1e --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/kratos_doxyfile @@ -0,0 +1,1610 @@ +# Doxyfile 1.6.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Kratos + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 2.1.0 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../documents + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 16 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set +# FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../kratos \ + ../applications + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = ../applications/ULFapplication/custom_external_libraries \ + ../applications/structural_application/custom_external_libraries \ + ../applications/MeshingApplication/custom_external_libraries \ + ../applications/PFEMapplication/custom_external_libraries \ + ../applications/FSIapplication/custom_external_libraries \ + ../applications/petsc_application/custom_external_libraries \ + ../applications/ExternalSolversApplication/custom_external_libraries + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = */.svn/* \ + */boost/* \ + */custom_problemtype/* \ + */test_examples/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = amsmath,amsfonts,amssymb + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/applications/GeoMechanicsApplication/documents/tutorials/main.aux b/applications/GeoMechanicsApplication/documents/tutorials/main.aux new file mode 100644 index 000000000000..595ff51c216e --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/main.aux @@ -0,0 +1,140 @@ +\relax +\providecommand\hyper@newdestlabel[2]{} +\providecommand\BKM@entry[2]{} +\providecommand{\transparent@use}[1]{} +\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument} +\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined +\global\let\oldcontentsline\contentsline +\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} +\global\let\oldnewlabel\newlabel +\gdef\newlabel#1#2{\newlabelxx{#1}#2} +\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} +\AtEndDocument{\ifx\hyper@anchor\@undefined +\let\contentsline\oldcontentsline +\let\newlabel\oldnewlabel +\fi} +\fi} +\global\let\hyper@last\relax +\gdef\HyperFirstAtBeginDocument#1{#1} +\providecommand\HyField@AuxAddToFields[1]{} +\providecommand\HyField@AuxAddToCoFields[2]{} +\bibstyle{deltares_chicago_like} +\babel@aux{english}{} +\BKM@entry{id=1,dest={636861707465722A2E32},srcline={16},srcfile={6D61696E2E746578}}{4C697374206F662046696775726573} +\@writefile{toc}{\contentsline {chapter}{List of Figures}{iv}{chapter*.2}\protected@file@percent } +\BKM@entry{id=2,dest={636861707465722A2E33},srcline={16},srcfile={6D61696E2E746578}}{4C697374206F66205461626C6573} +\@writefile{toc}{\contentsline {chapter}{List of Tables}{v}{chapter*.3}\protected@file@percent } +\BKM@entry{id=3,dest={636861707465722E31},srcline={20},srcfile={6D61696E2E746578}}{3120496E74726F64756374696F6E} +\@writefile{toc}{\contentsline {chapter}{\numberline {1}Introduction}{1}{chapter.1}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\BKM@entry{id=4,dest={636861707465722E32},srcline={24},srcfile={6D61696E2E746578}}{322047657474696E672073746172746564} +\@writefile{toc}{\contentsline {chapter}{\numberline {2}Getting started}{2}{chapter.2}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\BKM@entry{id=5,dest={636861707465722E33},srcline={27},srcfile={6D61696E2E746578}}{33204372656174652067656F6D65747279} +\BKM@entry{id=6,dest={73756273656374696F6E2E332E302E31},srcline={1},srcfile={4368617074657243726561746547656F6D657472792E746578}}{332E302E3120437265617465206C696E6573} +\BKM@entry{id=7,dest={73756273656374696F6E2E332E302E32},srcline={31},srcfile={4368617074657243726561746547656F6D657472792E746578}}{332E302E3220437265617465207375726661636573} +\@writefile{toc}{\contentsline {chapter}{\numberline {3}Create geometry}{4}{chapter.3}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.0.1}Create lines}{4}{subsection.3.0.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {3.0.2}Create surfaces}{4}{subsection.3.0.2}\protected@file@percent } +\BKM@entry{id=8,dest={73756273656374696F6E2E332E302E33},srcline={59},srcfile={4368617074657243726561746547656F6D657472792E746578}}{332E302E332043726561746520766F6C756D6573} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.0.3}Create volumes}{5}{subsection.3.0.3}\protected@file@percent } +\BKM@entry{id=9,dest={636861707465722E34},srcline={30},srcfile={6D61696E2E746578}}{3420446566696E652070726F626C656D} +\BKM@entry{id=10,dest={73756273656374696F6E2E342E302E31},srcline={4},srcfile={43686170746572446566696E6550726F626C656D2E746578}}{342E302E31204D6174657269616C73} +\BKM@entry{id=11,dest={73756273656374696F6E2E342E302E32},srcline={20},srcfile={43686170746572446566696E6550726F626C656D2E746578}}{342E302E3220426F756E6461727920636F6E646974696F6E73} +\BKM@entry{id=12,dest={73756273656374696F6E2E342E302E33},srcline={42},srcfile={43686170746572446566696E6550726F626C656D2E746578}}{342E302E33205374727563747572616C20656C656D656E747320616E6420696E7465726661636573} +\@writefile{toc}{\contentsline {chapter}{\numberline {4}Define problem}{6}{chapter.4}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\@writefile{toc}{\contentsline {subsection}{\numberline {4.0.1}Materials}{6}{subsection.4.0.1}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.0.2}Boundary conditions}{6}{subsection.4.0.2}\protected@file@percent } +\@writefile{toc}{\contentsline {subsection}{\numberline {4.0.3}Structural elements and interfaces}{6}{subsection.4.0.3}\protected@file@percent } +\BKM@entry{id=13,dest={636861707465722E35},srcline={33},srcfile={6D61696E2E746578}}{35204D657368696E67} +\@writefile{toc}{\contentsline {chapter}{\numberline {5}Meshing}{7}{chapter.5}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\BKM@entry{id=14,dest={636861707465722E36},srcline={36},srcfile={6D61696E2E746578}}{362043616C63756C6174696E67} +\@writefile{toc}{\contentsline {chapter}{\numberline {6}Calculating}{8}{chapter.6}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\BKM@entry{id=15,dest={636861707465722E37},srcline={39},srcfile={6D61696E2E746578}}{3720506F737450726F63657373} +\@writefile{toc}{\contentsline {chapter}{\numberline {7}PostProcess}{9}{chapter.7}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\BKM@entry{id=16,dest={636861707465722E38},srcline={43},srcfile={6D61696E2E746578}}{38205475746F7269616C20313A2044696B65} +\BKM@entry{id=17,dest={73656374696F6E2E382E31},srcline={3},srcfile={436861707465725475746F7269616C312E746578}}{382E312047656F6D65747279} +\@writefile{toc}{\contentsline {chapter}{\numberline {8}Tutorial 1: Dike}{10}{chapter.8}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\@writefile{toc}{\contentsline {section}{\numberline {8.1}Geometry}{10}{section.8.1}\protected@file@percent } +\@writefile{lot}{\contentsline {table}{\numberline {8.1}{\ignorespaces Outline geometry tutorial 1\relax }}{10}{table.caption.4}\protected@file@percent } +\providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}} +\newlabel{tab:tut1_outline}{{8.1}{10}{Outline geometry tutorial 1\relax }{table.caption.4}{}} +\newlabel{table:was:used:in:doc}{{8.1}{10}{Outline geometry tutorial 1\relax }{table.caption.4}{}} +\@writefile{lot}{\contentsline {table}{\numberline {8.2}{\ignorespaces Outline soil layer tutorial 1\relax }}{10}{table.caption.5}\protected@file@percent } +\newlabel{tab:tut1_outline_sl}{{8.2}{10}{Outline soil layer tutorial 1\relax }{table.caption.5}{}} +\newlabel{table:was:used:in:doc}{{8.2}{10}{Outline soil layer tutorial 1\relax }{table.caption.5}{}} +\@writefile{lot}{\contentsline {table}{\numberline {8.3}{\ignorespaces Verticals turning points phreatic line tutorial 1\relax }}{10}{table.caption.6}\protected@file@percent } +\newlabel{tab:tut1_verticals_water}{{8.3}{10}{Verticals turning points phreatic line tutorial 1\relax }{table.caption.6}{}} +\newlabel{table:was:used:in:doc}{{8.3}{10}{Verticals turning points phreatic line tutorial 1\relax }{table.caption.6}{}} +\BKM@entry{id=18,dest={73656374696F6E2E382E32},srcline={137},srcfile={436861707465725475746F7269616C312E746578}}{382E3220426F756E6461727920636F6E646974696F6E73} +\BKM@entry{id=19,dest={73656374696F6E2E382E33},srcline={153},srcfile={436861707465725475746F7269616C312E746578}}{382E33204D6174657269616C73} +\@writefile{lof}{\contentsline {figure}{\numberline {8.1}{\ignorespaces All outlines tutorial 1\relax }}{11}{figure.caption.7}\protected@file@percent } +\newlabel{fig:tut1_all_outline}{{8.1}{11}{All outlines tutorial 1\relax }{figure.caption.7}{}} +\newlabel{fig:was:used:in:doc}{{8.1}{11}{All outlines tutorial 1\relax }{figure.caption.7}{}} +\@writefile{lot}{\contentsline {table}{\numberline {8.4}{\ignorespaces Surfaces tutorial 1\relax }}{11}{table.caption.8}\protected@file@percent } +\newlabel{tab:tut1_surfaces}{{8.4}{11}{Surfaces tutorial 1\relax }{table.caption.8}{}} +\newlabel{table:was:used:in:doc}{{8.4}{11}{Surfaces tutorial 1\relax }{table.caption.8}{}} +\@writefile{lof}{\contentsline {figure}{\numberline {8.2}{\ignorespaces Geometry tutorial 1\relax }}{11}{figure.caption.9}\protected@file@percent } +\newlabel{fig:tut1_geometry}{{8.2}{11}{Geometry tutorial 1\relax }{figure.caption.9}{}} +\newlabel{fig:was:used:in:doc}{{8.2}{11}{Geometry tutorial 1\relax }{figure.caption.9}{}} +\@writefile{toc}{\contentsline {section}{\numberline {8.2}Boundary conditions}{11}{section.8.2}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {8.3}Materials}{11}{section.8.3}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {8.3}{\ignorespaces Dirichlet constraints window\relax }}{12}{figure.caption.10}\protected@file@percent } +\newlabel{fig:tut1_dirichlet_constraints_window}{{8.3}{12}{Dirichlet constraints window\relax }{figure.caption.10}{}} +\newlabel{fig:was:used:in:doc}{{8.3}{12}{Dirichlet constraints window\relax }{figure.caption.10}{}} +\@writefile{lof}{\contentsline {figure}{\numberline {8.4}{\ignorespaces Clay parameters tutorial 1\relax }}{12}{figure.caption.11}\protected@file@percent } +\newlabel{fig:tut1_clay_mat}{{8.4}{12}{Clay parameters tutorial 1\relax }{figure.caption.11}{}} +\newlabel{fig:was:used:in:doc}{{8.4}{12}{Clay parameters tutorial 1\relax }{figure.caption.11}{}} +\BKM@entry{id=20,dest={73656374696F6E2E382E34},srcline={182},srcfile={436861707465725475746F7269616C312E746578}}{382E34205761746572} +\@writefile{lof}{\contentsline {figure}{\numberline {8.5}{\ignorespaces Sand parameters tutorial 1\relax }}{13}{figure.caption.12}\protected@file@percent } +\newlabel{fig:tut1_sand_mat}{{8.5}{13}{Sand parameters tutorial 1\relax }{figure.caption.12}{}} +\newlabel{fig:was:used:in:doc}{{8.5}{13}{Sand parameters tutorial 1\relax }{figure.caption.12}{}} +\@writefile{toc}{\contentsline {section}{\numberline {8.4}Water}{13}{section.8.4}\protected@file@percent } +\BKM@entry{id=21,dest={73656374696F6E2E382E35},srcline={217},srcfile={436861707465725475746F7269616C312E746578}}{382E35204C6F616473} +\@writefile{lof}{\contentsline {figure}{\numberline {8.6}{\ignorespaces Dike parameters tutorial 1\relax }}{14}{figure.caption.13}\protected@file@percent } +\newlabel{fig:tut1_dike_mat}{{8.6}{14}{Dike parameters tutorial 1\relax }{figure.caption.13}{}} +\newlabel{fig:was:used:in:doc}{{8.6}{14}{Dike parameters tutorial 1\relax }{figure.caption.13}{}} +\@writefile{toc}{\contentsline {section}{\numberline {8.5}Loads}{14}{section.8.5}\protected@file@percent } +\BKM@entry{id=22,dest={73656374696F6E2E382E36},srcline={227},srcfile={436861707465725475746F7269616C312E746578}}{382E36204D657368696E67} +\@writefile{lof}{\contentsline {figure}{\numberline {8.7}{\ignorespaces River water level tutorial 1\relax }}{15}{figure.caption.14}\protected@file@percent } +\newlabel{fig:tut1_river_level}{{8.7}{15}{River water level tutorial 1\relax }{figure.caption.14}{}} +\newlabel{fig:was:used:in:doc}{{8.7}{15}{River water level tutorial 1\relax }{figure.caption.14}{}} +\@writefile{toc}{\contentsline {section}{\numberline {8.6}Meshing}{15}{section.8.6}\protected@file@percent } +\BKM@entry{id=23,dest={73656374696F6E2E382E37},srcline={238},srcfile={436861707465725475746F7269616C312E746578}}{382E372050726F6A65637420506172616D6574657273} +\BKM@entry{id=24,dest={73656374696F6E2E382E38},srcline={248},srcfile={436861707465725475746F7269616C312E746578}}{382E382043616C63756C617465} +\BKM@entry{id=25,dest={73656374696F6E2E382E39},srcline={257},srcfile={436861707465725475746F7269616C312E746578}}{382E3920506F73742D70726F6365737320706172742031} +\@writefile{lof}{\contentsline {figure}{\numberline {8.8}{\ignorespaces River load tutorial 1\relax }}{16}{figure.caption.15}\protected@file@percent } +\newlabel{fig:tut1_river_load}{{8.8}{16}{River load tutorial 1\relax }{figure.caption.15}{}} +\newlabel{fig:was:used:in:doc}{{8.8}{16}{River load tutorial 1\relax }{figure.caption.15}{}} +\@writefile{toc}{\contentsline {section}{\numberline {8.7}Project Parameters}{16}{section.8.7}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {8.8}Calculate}{16}{section.8.8}\protected@file@percent } +\BKM@entry{id=26,dest={73656374696F6E2E382E3130},srcline={273},srcfile={436861707465725475746F7269616C312E746578}}{382E31302053746167656420636F6E737472756374696F6E} +\@writefile{lof}{\contentsline {figure}{\numberline {8.9}{\ignorespaces Dike water level tutorial 1\relax }}{17}{figure.caption.16}\protected@file@percent } +\newlabel{fig:tut1_dike_level}{{8.9}{17}{Dike water level tutorial 1\relax }{figure.caption.16}{}} +\newlabel{fig:was:used:in:doc}{{8.9}{17}{Dike water level tutorial 1\relax }{figure.caption.16}{}} +\@writefile{toc}{\contentsline {section}{\numberline {8.9}Post-process part 1}{17}{section.8.9}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {8.10}Staged construction}{17}{section.8.10}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {8.10}{\ignorespaces Contour results tutorial 1 part 1, top to bottom: water pressure, x-displacement, y-displacement\relax }}{18}{figure.caption.17}\protected@file@percent } +\newlabel{fig:tut1_p1_results}{{8.10}{18}{Contour results tutorial 1 part 1, top to bottom: water pressure, x-displacement, y-displacement\relax }{figure.caption.17}{}} +\newlabel{fig:was:used:in:doc}{{8.10}{18}{Contour results tutorial 1 part 1, top to bottom: water pressure, x-displacement, y-displacement\relax }{figure.caption.17}{}} +\BKM@entry{id=27,dest={73656374696F6E2E382E3131},srcline={341},srcfile={436861707465725475746F7269616C312E746578}}{382E31312043616C63756C6174652073746167656420636F6E737472756374696F6E} +\BKM@entry{id=28,dest={73656374696F6E2E382E3132},srcline={353},srcfile={436861707465725475746F7269616C312E746578}}{382E313220506F73742D70726F6365737320706172742032} +\@writefile{toc}{\contentsline {section}{\numberline {8.11}Calculate staged construction}{19}{section.8.11}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {8.12}Post-process part 2}{19}{section.8.12}\protected@file@percent } +\newlabel{LastPage}{{}{19}{}{page.19}{}} +\xdef\lastpage@lastpage{19} +\xdef\lastpage@lastpageHy{19} diff --git a/applications/GeoMechanicsApplication/documents/tutorials/main.pdf b/applications/GeoMechanicsApplication/documents/tutorials/main.pdf new file mode 100644 index 000000000000..dce4844698ef Binary files /dev/null and b/applications/GeoMechanicsApplication/documents/tutorials/main.pdf differ diff --git a/applications/GeoMechanicsApplication/documents/tutorials/main.tex b/applications/GeoMechanicsApplication/documents/tutorials/main.tex new file mode 100644 index 000000000000..aae44825804b --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/main.tex @@ -0,0 +1,49 @@ +\documentclass{deltares_manual} +\usepackage{graphicx} +\usepackage{enumitem} +\graphicspath{ {./figures/} } + +\begin{document} + + +\title{Reference Manual Kratos GeoMechanics} +\subtitle{} + + +\manualtype{} + +\author{Aron Noordam, Vahid Galavi} +\deltarestitle +%------------------------------------------------------------------------------ + +% Text body +\chapter{Introduction} +\input{ChapterIntroduction} + + +\chapter{Getting started} +\input{ChapterGettingStarted} + +\chapter{Create geometry} +\input{ChapterCreateGeometry} + +\chapter{Define problem} +\input{ChapterDefineProblem} + +\chapter{Meshing} +\input{ChapterMeshing} + +\chapter{Calculating} +\input{ChapterCalculating} + +\chapter{PostProcess} +\input{ChapterPostProcess} + + +\chapter{Tutorial 1: Dike} +\input{ChapterTutorial1} + + +%------------------------------------------------------------------------------ + +\end{document} \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/documents/tutorials/main.toc b/applications/GeoMechanicsApplication/documents/tutorials/main.toc new file mode 100644 index 000000000000..c77e2dd16f01 --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/main.toc @@ -0,0 +1,29 @@ +\babel@toc {english}{} +\contentsline {chapter}{List of Figures}{iv}{chapter*.2}% +\contentsline {chapter}{List of Tables}{v}{chapter*.3}% +\contentsline {chapter}{\numberline {1}Introduction}{1}{chapter.1}% +\contentsline {chapter}{\numberline {2}Getting started}{2}{chapter.2}% +\contentsline {chapter}{\numberline {3}Create geometry}{4}{chapter.3}% +\contentsline {subsection}{\numberline {3.0.1}Create lines}{4}{subsection.3.0.1}% +\contentsline {subsection}{\numberline {3.0.2}Create surfaces}{4}{subsection.3.0.2}% +\contentsline {subsection}{\numberline {3.0.3}Create volumes}{5}{subsection.3.0.3}% +\contentsline {chapter}{\numberline {4}Define problem}{6}{chapter.4}% +\contentsline {subsection}{\numberline {4.0.1}Materials}{6}{subsection.4.0.1}% +\contentsline {subsection}{\numberline {4.0.2}Boundary conditions}{6}{subsection.4.0.2}% +\contentsline {subsection}{\numberline {4.0.3}Structural elements and interfaces}{6}{subsection.4.0.3}% +\contentsline {chapter}{\numberline {5}Meshing}{7}{chapter.5}% +\contentsline {chapter}{\numberline {6}Calculating}{8}{chapter.6}% +\contentsline {chapter}{\numberline {7}PostProcess}{9}{chapter.7}% +\contentsline {chapter}{\numberline {8}Tutorial 1: Dike}{10}{chapter.8}% +\contentsline {section}{\numberline {8.1}Geometry}{10}{section.8.1}% +\contentsline {section}{\numberline {8.2}Boundary conditions}{11}{section.8.2}% +\contentsline {section}{\numberline {8.3}Materials}{11}{section.8.3}% +\contentsline {section}{\numberline {8.4}Water}{13}{section.8.4}% +\contentsline {section}{\numberline {8.5}Loads}{14}{section.8.5}% +\contentsline {section}{\numberline {8.6}Meshing}{15}{section.8.6}% +\contentsline {section}{\numberline {8.7}Project Parameters}{16}{section.8.7}% +\contentsline {section}{\numberline {8.8}Calculate}{16}{section.8.8}% +\contentsline {section}{\numberline {8.9}Post-process part 1}{17}{section.8.9}% +\contentsline {section}{\numberline {8.10}Staged construction}{17}{section.8.10}% +\contentsline {section}{\numberline {8.11}Calculate staged construction}{19}{section.8.11}% +\contentsline {section}{\numberline {8.12}Post-process part 2}{19}{section.8.12}% diff --git a/applications/GeoMechanicsApplication/documents/tutorials/template_scripts/tutorial_1/MainKratos.py b/applications/GeoMechanicsApplication/documents/tutorials/template_scripts/tutorial_1/MainKratos.py new file mode 100644 index 000000000000..e463472eef4e --- /dev/null +++ b/applications/GeoMechanicsApplication/documents/tutorials/template_scripts/tutorial_1/MainKratos.py @@ -0,0 +1,27 @@ +from __future__ import print_function, absolute_import, division #makes KratosMultiphysics backward compatible with python 2.6 and 2.7 +import os +import KratosMultiphysics +import KratosMultiphysics.LinearSolversApplication +# import KratosMultiphysics.TrilinosApplication as TrilinosApplication +import KratosMultiphysics.StructuralMechanicsApplication +import KratosMultiphysics.GeoMechanicsApplication + +from KratosMultiphysics.GeoMechanicsApplication.geomechanics_analysis import GeoMechanicsAnalysis + +if __name__ == "__main__": + + project_paths = [r"D:\software_development\Kratos\applications\GeoMechanicsApplication\test_examples\tutorial_1_stage_1.gid", + r"D:\software_development\Kratos\applications\GeoMechanicsApplication\test_examples\tutorial_1_stage_2.gid", + r"D:\software_development\Kratos\applications\GeoMechanicsApplication\test_examples\tutorial_1_stage_3.gid", + r"D:\software_development\Kratos\applications\GeoMechanicsApplication\test_examples\tutorial_1_stage_4.gid", + ] + + model = KratosMultiphysics.Model() + for project_path in project_paths: + os.chdir(project_path) + + with open("ProjectParameters.json",'r') as parameter_file: + parameters = KratosMultiphysics.Parameters(parameter_file.read()) + + simulation = GeoMechanicsAnalysis(model,parameters) + simulation.Run() diff --git a/applications/GeoMechanicsApplication/geo_mechanics_application.cpp b/applications/GeoMechanicsApplication/geo_mechanics_application.cpp new file mode 100644 index 000000000000..ea129319c156 --- /dev/null +++ b/applications/GeoMechanicsApplication/geo_mechanics_application.cpp @@ -0,0 +1,267 @@ +// KRATOS___ +// // ) ) +// // ___ ___ +// // ____ //___) ) // ) ) +// // / / // // / / +// ((____/ / ((____ ((___/ / MECHANICS +// +// License: geo_mechanics_application/license.txt +// +// Main authors: Vahid Galavi +// + + +// System includes + + +// External includes + +// Project includes +#include "includes/define.h" +#include "geometries/triangle_2d_3.h" +#include "geometries/triangle_2d_6.h" +#include "geometries/quadrilateral_2d_4.h" +#include "geometries/quadrilateral_2d_8.h" +#include "geometries/quadrilateral_2d_9.h" +#include "geometries/quadrilateral_interface_2d_4.h" +#include "geometries/tetrahedra_3d_4.h" +#include "geometries/tetrahedra_3d_10.h" +#include "geometries/prism_interface_3d_6.h" +#include "geometries/hexahedra_3d_8.h" +#include "geometries/hexahedra_3d_20.h" +#include "geometries/hexahedra_3d_27.h" +#include "geometries/hexahedra_interface_3d_8.h" +#include "geometries/point_2d.h" +#include "geometries/point_3d.h" +#include "geometries/line_2d_2.h" +#include "geometries/line_2d_3.h" +#include "geometries/triangle_3d_3.h" +#include "geometries/triangle_3d_6.h" +#include "geometries/quadrilateral_3d_4.h" +#include "geometries/quadrilateral_3d_8.h" +#include "geometries/quadrilateral_3d_9.h" +#include "geometries/quadrilateral_interface_3d_4.h" +#include "includes/variables.h" + + +// Application includes +#include "geo_mechanics_application.h" +#include "geo_mechanics_application_variables.h" + + +namespace Kratos { +// We define the node type +typedef Node<3> NodeType; + +KratosGeoMechanicsApplication::KratosGeoMechanicsApplication(): + KratosApplication("GeoMechanicsApplication") + + // small strain elements + + // drained small strain elements + + // undrained small strain elements + + // small strain FIC elements + + // small strain different order elements + + // small strain interface elements + + // Updated-Lagrangian elements + + // Updated-Lagrangian different order elements + + // geo structural elements + + // conditions + + {} + +void KratosGeoMechanicsApplication::Register() { + // calling base class register to register Kratos components + KratosApplication::Register(); + KRATOS_INFO("") << " KRATOS___ \n" + << " // ) ) \n" + << " // ___ ___ \n" + << " // ____ //___) ) // ) ) \n" + << " // / / // // / / \n" + << " ((____/ / ((____ ((___/ / MECHANICS\n" + << " Initializing KratosGeoMechanicsApplication..." << std::endl; + + + + //Register Elements + // Small strain elements + + // Drained small strain elements + + // Undrained small strain elements + + // Small strain FIC elements + + // Small strain different order elements + + // Small strain interface elements + + // Updated-Lagranian elements + + // Updated-Lagrangian different order elements + + // Register geo structural elements + + //Register Conditions + + //Register Constitutive Laws + + //Register Variables + KRATOS_REGISTER_VARIABLE( VELOCITY_COEFFICIENT ) + KRATOS_REGISTER_VARIABLE( DT_PRESSURE_COEFFICIENT ) + + KRATOS_REGISTER_VARIABLE( DT_WATER_PRESSURE ) + KRATOS_REGISTER_VARIABLE( NORMAL_FLUID_FLUX ) + + KRATOS_REGISTER_VARIABLE( DENSITY_SOLID ) + KRATOS_REGISTER_VARIABLE( BULK_MODULUS_SOLID ) + KRATOS_REGISTER_VARIABLE( BULK_MODULUS_FLUID ) + + KRATOS_REGISTER_VARIABLE( K0_MAIN_DIRECTION ) + KRATOS_REGISTER_VARIABLE( K0_VALUE_XX ) + KRATOS_REGISTER_VARIABLE( K0_VALUE_YY ) + KRATOS_REGISTER_VARIABLE( K0_VALUE_ZZ ) + + KRATOS_REGISTER_VARIABLE( PERMEABILITY_XX ) + KRATOS_REGISTER_VARIABLE( PERMEABILITY_YY ) + KRATOS_REGISTER_VARIABLE( PERMEABILITY_ZZ ) + KRATOS_REGISTER_VARIABLE( PERMEABILITY_XY ) + KRATOS_REGISTER_VARIABLE( PERMEABILITY_YZ ) + KRATOS_REGISTER_VARIABLE( PERMEABILITY_ZX ) + + KRATOS_REGISTER_VARIABLE( MINIMUM_JOINT_WIDTH ) + KRATOS_REGISTER_VARIABLE( TRANSVERSAL_PERMEABILITY ) + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS( FLUID_FLUX_VECTOR ) + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS( LOCAL_FLUID_FLUX_VECTOR ) + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS( LOCAL_STRESS_VECTOR ) + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS( LOCAL_RELATIVE_DISPLACEMENT_VECTOR ) + KRATOS_REGISTER_VARIABLE( PERMEABILITY_MATRIX ) + KRATOS_REGISTER_VARIABLE( LOCAL_PERMEABILITY_MATRIX ) + + KRATOS_REGISTER_VARIABLE( CRITICAL_DISPLACEMENT ) + KRATOS_REGISTER_3D_VARIABLE_WITH_COMPONENTS( TOTAL_DISPLACEMENT ) + + KRATOS_REGISTER_VARIABLE( IS_CONVERGED ) + + KRATOS_REGISTER_VARIABLE( TOTAL_STRESS_TENSOR ) + KRATOS_REGISTER_VARIABLE( TOTAL_STRESS_VECTOR ) + + KRATOS_REGISTER_VARIABLE( CAUCHY_STRAIN_TENSOR ) + KRATOS_REGISTER_VARIABLE( CAUCHY_STRAIN_VECTOR ) + + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE ) + KRATOS_REGISTER_VARIABLE( ARC_LENGTH_LAMBDA ) + KRATOS_REGISTER_VARIABLE( ARC_LENGTH_RADIUS_FACTOR ) + + KRATOS_REGISTER_VARIABLE( TIME_UNIT_CONVERTER ) + + KRATOS_REGISTER_VARIABLE( LOCAL_EQUIVALENT_STRAIN ) + KRATOS_REGISTER_VARIABLE( NONLOCAL_EQUIVALENT_STRAIN ) + + KRATOS_REGISTER_VARIABLE( JOINT_WIDTH ) + + KRATOS_REGISTER_VARIABLE( NODAL_SMOOTHING ) + KRATOS_REGISTER_VARIABLE( NODAL_CAUCHY_STRESS_TENSOR ) + KRATOS_REGISTER_VARIABLE( NODAL_DAMAGE_VARIABLE ) + KRATOS_REGISTER_VARIABLE( NODAL_JOINT_AREA ) + KRATOS_REGISTER_VARIABLE( NODAL_JOINT_WIDTH ) + KRATOS_REGISTER_VARIABLE( NODAL_JOINT_DAMAGE ) + + KRATOS_REGISTER_VARIABLE( RESET_DISPLACEMENTS ) + KRATOS_REGISTER_VARIABLE( CONSIDER_GEOMETRIC_STIFFNESS ) + + KRATOS_REGISTER_VARIABLE( USE_CONSISTENT_MASS_MATRIX) + + KRATOS_REGISTER_VARIABLE( IGNORE_UNDRAINED ) + + KRATOS_REGISTER_VARIABLE( SATURATED_SATURATION ) + KRATOS_REGISTER_VARIABLE( RESIDUAL_SATURATION ) + KRATOS_REGISTER_VARIABLE( VAN_GENUCHTEN_AIR_ENTRY_PRESSURE ) + KRATOS_REGISTER_VARIABLE( VAN_GENUCHTEN_GN ) + KRATOS_REGISTER_VARIABLE( VAN_GENUCHTEN_GL ) + KRATOS_REGISTER_VARIABLE( MINIMUM_RELATIVE_PERMEABILITY ) + + KRATOS_REGISTER_VARIABLE( RETENTION_LAW ) + KRATOS_REGISTER_VARIABLE( DEGREE_OF_SATURATION ) + KRATOS_REGISTER_VARIABLE( EFFECTIVE_SATURATION ) + KRATOS_REGISTER_VARIABLE( BISHOP_COEFICIENT ) + KRATOS_REGISTER_VARIABLE( DERIVATIVE_OF_SATURATION ) + KRATOS_REGISTER_VARIABLE( RELATIVE_PERMEABILITY ) + + // UDSM + KRATOS_REGISTER_VARIABLE( UDSM_NAME ) // Also for UMAT + KRATOS_REGISTER_VARIABLE( UDSM_NUMBER ) + KRATOS_REGISTER_VARIABLE( IS_FORTRAN_UDSM ) // Also for UMAT + + KRATOS_REGISTER_VARIABLE( UMAT_PARAMETERS ) + + KRATOS_REGISTER_VARIABLE(NUMBER_OF_UMAT_STATE_VARIABLES) + KRATOS_REGISTER_VARIABLE(NUMBER_OF_UMAT_PARAMETERS) + + KRATOS_REGISTER_VARIABLE( STATE_VARIABLES ) + + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_1 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_2 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_3 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_4 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_5 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_6 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_7 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_8 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_9 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_10 ) + + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_11 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_12 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_13 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_14 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_15 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_16 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_17 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_18 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_19 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_20 ) + + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_21 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_22 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_23 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_24 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_25 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_26 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_27 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_28 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_29 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_30 ) + + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_31 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_32 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_33 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_34 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_35 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_36 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_37 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_38 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_39 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_40 ) + + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_41 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_42 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_43 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_44 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_45 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_46 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_47 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_48 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_49 ) + KRATOS_REGISTER_VARIABLE( STATE_VARIABLE_50 ) + + } +} // namespace Kratos. diff --git a/applications/GeoMechanicsApplication/geo_mechanics_application.h b/applications/GeoMechanicsApplication/geo_mechanics_application.h new file mode 100644 index 000000000000..388116478739 --- /dev/null +++ b/applications/GeoMechanicsApplication/geo_mechanics_application.h @@ -0,0 +1,277 @@ +// KRATOS___ +// // ) ) +// // ___ ___ +// // ____ //___) ) // ) ) +// // / / // // / / +// ((____/ / ((____ ((___/ / MECHANICS +// +// License: geo_mechanics_application/license.txt +// +// Main authors: Vahid Galavi +// + + +#if !defined(KRATOS_GEO_MECHANICS_APPLICATION_H_INCLUDED ) +#define KRATOS_GEO_MECHANICS_APPLICATION_H_INCLUDED + + +// System includes +#include +#include + + +// External includes + + +// Project includes +#include "includes/define.h" +#include "includes/kratos_application.h" +#include "includes/variables.h" + +// Application includes +#include "geo_mechanics_application_variables.h" + +// conditions + +// elements + +/* geo structural element */ + +// constitutive models + + +namespace Kratos { + +///@name Kratos Globals +///@{ + +///@} +///@name Type Definitions +///@{ + +///@} +///@name Enum's +///@{ + +///@} +///@name Functions +///@{ + +///@} +///@name Kratos Classes +///@{ + +/// Short class definition. +/** Detail class definition. +*/ +class KRATOS_API(GEO_MECHANICS_APPLICATION) KratosGeoMechanicsApplication : public KratosApplication { +public: + ///@name Type Definitions + ///@{ + + + /// Pointer definition of KratosGeoMechanicsApplication + KRATOS_CLASS_POINTER_DEFINITION(KratosGeoMechanicsApplication); + + ///@} + ///@name Life Cycle + ///@{ + + /// Default constructor. + KratosGeoMechanicsApplication(); + + /// Destructor. + virtual ~KratosGeoMechanicsApplication(){} + + + ///@} + ///@name Operators + ///@{ + + + ///@} + ///@name Operations + ///@{ + + virtual void Register() override; + + + + ///@} + ///@name Access + ///@{ + + + ///@} + ///@name Inquiry + ///@{ + + + ///@} + ///@name Input and output + ///@{ + + /// Turn back information as a string. + virtual std::string Info() const override + { + return "KratosGeoMechanicsApplication"; + } + + /// Print information about this object. + virtual void PrintInfo(std::ostream& rOStream) const override + { + rOStream << Info(); + PrintData(rOStream); + } + + ///// Print object's data. + virtual void PrintData(std::ostream& rOStream) const override + { + KRATOS_WATCH("in KratosGeoMechanicsApplication"); + KRATOS_WATCH(KratosComponents::GetComponents().size() ); + + rOStream << "Variables:" << std::endl; + KratosComponents().PrintData(rOStream); + rOStream << std::endl; + rOStream << "Elements:" << std::endl; + KratosComponents().PrintData(rOStream); + rOStream << std::endl; + rOStream << "Conditions:" << std::endl; + KratosComponents().PrintData(rOStream); + } + + + ///@} + ///@name Friends + ///@{ + + + ///@} + +protected: + ///@name Protected static Member Variables + ///@{ + + + ///@} + ///@name Protected member Variables + ///@{ + + + ///@} + ///@name Protected Operators + ///@{ + + + ///@} + ///@name Protected Operations + ///@{ + + + ///@} + ///@name Protected Access + ///@{ + + + ///@} + ///@name Protected Inquiry + ///@{ + + + ///@} + ///@name Protected LifeCycle + ///@{ + + + ///@} + +private: + ///@name Static Member Variables + ///@{ + + // static const ApplicationCondition msApplicationCondition; + + ///@} + ///@name Member Variables + ///@{ + + // const Elem2D mElem2D; + // const Elem3D mElem3D; + + ///@} + ///@name Private Operators + ///@{ + + + ///@} + ///@name Private Operations + ///@{ + + + ///@} + ///@name Private Access + ///@{ + + + ///@} + ///@name Private Inquiry + ///@{ + + + ///@} + ///@name Un accessible methods + ///@{ + + // elements + // small strain elements: + + // small strain drained elements: + + // small strain undrained elements: + + // FIC elements + + // Small strain different order elements + + // interface elements + + // Updated-Lagrangian elements: + + + // Updated-Lagrangian different order elements + + // geo structural element + + // conditions + + + // constitutive models + + /// Assignment operator. + KratosGeoMechanicsApplication& operator=(KratosGeoMechanicsApplication const& rOther); + + /// Copy constructor. + KratosGeoMechanicsApplication(KratosGeoMechanicsApplication const& rOther); + + + ///@} + +}; // Class KratosGeoMechanicsApplication + +///@} + + +///@name Type Definitions +///@{ + + +///@} +///@name Input and output +///@{ + +///@} + + +} // namespace Kratos. + +#endif // KRATOS_GEO_MECHANICS_APPLICATION_H_INCLUDED defined diff --git a/applications/GeoMechanicsApplication/geo_mechanics_application_constants.h b/applications/GeoMechanicsApplication/geo_mechanics_application_constants.h new file mode 100644 index 000000000000..e0673ebd9781 --- /dev/null +++ b/applications/GeoMechanicsApplication/geo_mechanics_application_constants.h @@ -0,0 +1,87 @@ +// KRATOS___ +// // ) ) +// // ___ ___ +// // ____ //___) ) // ) ) +// // / / // // / / +// ((____/ / ((____ ((___/ / MECHANICS +// +// License: geo_mechanics_application/license.txt +// +// Main authors: Vahid Galavi +// + +#if !defined(KRATOS_GEO_MECHANICS_APPLICATION_CONSTANTS_H_INCLUDED ) +#define KRATOS_GEO_MECHANICS_APPLICATION_CONSTANTS_H_INCLUDED + +// System includes + +// External includes + +// Project includes +#include "includes/define.h" + + +namespace Kratos +{ + /* Contants used in GeoMechanicsApplication */ + // The size type definition + typedef std::size_t SizeType; + + + // Static definition of the dimension + constexpr SizeType N_DIM_3D = 3; + constexpr SizeType N_DIM_2D = 2; + constexpr SizeType N_DIM_1D = 1; + + // Limits + constexpr double TINY = 1.0e-60; + constexpr double LARGE = 1.0e10; + + // factor for pore pressure calculations: 1: mechanical sign convention, -1: soil mechanics sign convention + constexpr double PORE_PRESSURE_SIGN_FACTOR = 1.0; + + // Static definition of the VoigtSize + constexpr SizeType VOIGT_SIZE_3D = 6; + constexpr SizeType VOIGT_SIZE_2D_PLANE_STRESS = 3; + constexpr SizeType VOIGT_SIZE_2D_PLANE_STRAIN = 4; // This needs to be changed + constexpr SizeType VOIGT_SIZE_2D_AXISYMMETRIC = 4; + constexpr SizeType VOIGT_SIZE_2D_INTERFACE = 2; + constexpr SizeType VOIGT_SIZE_3D_INTERFACE = 3; + + // stress/strain vector indices (3D): + enum indexStress3D: int{ INDEX_3D_XX, + INDEX_3D_YY, + INDEX_3D_ZZ, + INDEX_3D_XY, + INDEX_3D_YZ, + INDEX_3D_XZ }; + + // stress/strain vector indices (2D plane strain): + enum indexStress2DPlaneStrain: int{ INDEX_2D_PLANE_STRAIN_XX, + INDEX_2D_PLANE_STRAIN_YY, + INDEX_2D_PLANE_STRAIN_ZZ, + INDEX_2D_PLANE_STRAIN_XY }; + + // stress/strain vector indices (2D plane stress): + enum indexStress2DPlaneStress: int{ INDEX_2D_PLANE_STRESS_XX, + INDEX_2D_PLANE_STRESS_YY, + INDEX_2D_PLANE_STRESS_XY }; + + // stress/strain vector indices (2D axisymmetric): + enum indexStress2DAxisymmetric: int{ INDEX_2D_AXI_SYMMETRIC_XX, + INDEX_2D_AXI_SYMMETRIC_YY, + INDEX_2D_AXI_SYMMETRIC_RR, + INDEX_2D_AXI_SYMMETRIC_XY}; + + // stress/strain vector indices (2D interface): + enum indexStress2DInterface: int{ INDEX_2D_INTERFACE_XZ, + INDEX_2D_INTERFACE_ZZ }; + + // stress/strain vector indices (3D interface): + enum indexStress3DInterface: int{ INDEX_3D_INTERFACE_XZ, + INDEX_3D_INTERFACE_YZ, + INDEX_3D_INTERFACE_ZZ }; + +} + +#endif /* KRATOS_GEO_MECHANICS_APPLICATION_CONSTANTS_H_INCLUDED */ diff --git a/applications/GeoMechanicsApplication/geo_mechanics_application_variables.cpp b/applications/GeoMechanicsApplication/geo_mechanics_application_variables.cpp new file mode 100644 index 000000000000..0b5b5f59f818 --- /dev/null +++ b/applications/GeoMechanicsApplication/geo_mechanics_application_variables.cpp @@ -0,0 +1,170 @@ +// KRATOS___ +// // ) ) +// // ___ ___ +// // ____ //___) ) // ) ) +// // / / // // / / +// ((____/ / ((____ ((___/ / MECHANICS +// +// License: geo_mechanics_application/license.txt +// +// Main authors: Vahid Galavi +// + +#include "geo_mechanics_application_variables.h" + +namespace Kratos +{ +/* Variables from GeoMechanicsApplication */ + +KRATOS_CREATE_VARIABLE( double, VELOCITY_COEFFICIENT ) +KRATOS_CREATE_VARIABLE( double, DT_PRESSURE_COEFFICIENT ) + +KRATOS_CREATE_VARIABLE( double, DT_WATER_PRESSURE ) +KRATOS_CREATE_VARIABLE( double, NORMAL_FLUID_FLUX ) + +KRATOS_CREATE_VARIABLE( double, DENSITY_SOLID ) +KRATOS_CREATE_VARIABLE( double, BULK_MODULUS_SOLID ) +KRATOS_CREATE_VARIABLE( double, BULK_MODULUS_FLUID ) + +KRATOS_CREATE_VARIABLE( int, K0_MAIN_DIRECTION ) +KRATOS_CREATE_VARIABLE( double, K0_VALUE_XX ) +KRATOS_CREATE_VARIABLE( double, K0_VALUE_YY ) +KRATOS_CREATE_VARIABLE( double, K0_VALUE_ZZ ) + +KRATOS_CREATE_VARIABLE( double, PERMEABILITY_XX ) +KRATOS_CREATE_VARIABLE( double, PERMEABILITY_YY ) +KRATOS_CREATE_VARIABLE( double, PERMEABILITY_ZZ ) +KRATOS_CREATE_VARIABLE( double, PERMEABILITY_XY ) +KRATOS_CREATE_VARIABLE( double, PERMEABILITY_YZ ) +KRATOS_CREATE_VARIABLE( double, PERMEABILITY_ZX ) + +KRATOS_CREATE_VARIABLE( double, MINIMUM_JOINT_WIDTH ) +KRATOS_CREATE_VARIABLE( double, TRANSVERSAL_PERMEABILITY ) +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS( FLUID_FLUX_VECTOR ) +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS( LOCAL_FLUID_FLUX_VECTOR ) +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS( LOCAL_STRESS_VECTOR ) +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS( LOCAL_RELATIVE_DISPLACEMENT_VECTOR ) +KRATOS_CREATE_VARIABLE( Matrix, PERMEABILITY_MATRIX ) +KRATOS_CREATE_VARIABLE( Matrix, LOCAL_PERMEABILITY_MATRIX ) + +KRATOS_CREATE_VARIABLE( double, CRITICAL_DISPLACEMENT ) +KRATOS_CREATE_3D_VARIABLE_WITH_COMPONENTS(TOTAL_DISPLACEMENT) + +KRATOS_CREATE_VARIABLE( bool, IS_CONVERGED) + +KRATOS_CREATE_VARIABLE( Matrix, TOTAL_STRESS_TENSOR ) +KRATOS_CREATE_VARIABLE( Vector, TOTAL_STRESS_VECTOR ) + +KRATOS_CREATE_VARIABLE( Matrix, CAUCHY_STRAIN_TENSOR ) +KRATOS_CREATE_VARIABLE( Vector, CAUCHY_STRAIN_VECTOR ) + +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE ) +KRATOS_CREATE_VARIABLE( double, ARC_LENGTH_LAMBDA ) +KRATOS_CREATE_VARIABLE( double, ARC_LENGTH_RADIUS_FACTOR ) + +KRATOS_CREATE_VARIABLE( double, TIME_UNIT_CONVERTER ) + +KRATOS_CREATE_VARIABLE( double, LOCAL_EQUIVALENT_STRAIN ) +KRATOS_CREATE_VARIABLE( double, NONLOCAL_EQUIVALENT_STRAIN ) + +KRATOS_CREATE_VARIABLE( double, JOINT_WIDTH ) + +KRATOS_CREATE_VARIABLE( bool, NODAL_SMOOTHING ) +KRATOS_CREATE_VARIABLE( Matrix, NODAL_CAUCHY_STRESS_TENSOR ) +KRATOS_CREATE_VARIABLE( double, NODAL_DAMAGE_VARIABLE ) +KRATOS_CREATE_VARIABLE( double, NODAL_JOINT_AREA ) +KRATOS_CREATE_VARIABLE( double, NODAL_JOINT_WIDTH ) +KRATOS_CREATE_VARIABLE( double, NODAL_JOINT_DAMAGE ) + +KRATOS_CREATE_VARIABLE(bool, RESET_DISPLACEMENTS) +KRATOS_CREATE_VARIABLE(bool, CONSIDER_GEOMETRIC_STIFFNESS) + +KRATOS_CREATE_VARIABLE(bool, USE_CONSISTENT_MASS_MATRIX) + +KRATOS_CREATE_VARIABLE(bool, IGNORE_UNDRAINED) + +// retention models +KRATOS_CREATE_VARIABLE(double, SATURATED_SATURATION ) +KRATOS_CREATE_VARIABLE(double, RESIDUAL_SATURATION ) +KRATOS_CREATE_VARIABLE(double, VAN_GENUCHTEN_AIR_ENTRY_PRESSURE ) +KRATOS_CREATE_VARIABLE(double, VAN_GENUCHTEN_GN ) +KRATOS_CREATE_VARIABLE(double, VAN_GENUCHTEN_GL ) +KRATOS_CREATE_VARIABLE(double, MINIMUM_RELATIVE_PERMEABILITY ) + +KRATOS_CREATE_VARIABLE(std::string, RETENTION_LAW ) +KRATOS_CREATE_VARIABLE(double, DEGREE_OF_SATURATION ) +KRATOS_CREATE_VARIABLE(double, EFFECTIVE_SATURATION ) +KRATOS_CREATE_VARIABLE(double, BISHOP_COEFICIENT ) +KRATOS_CREATE_VARIABLE(double, DERIVATIVE_OF_SATURATION ) +KRATOS_CREATE_VARIABLE(double, RELATIVE_PERMEABILITY ) + +// UDSM +KRATOS_CREATE_VARIABLE( std::string, UDSM_NAME ) // Also for UMAT +KRATOS_CREATE_VARIABLE( int, UDSM_NUMBER ) +KRATOS_CREATE_VARIABLE( bool, IS_FORTRAN_UDSM ) // Also for UMAT + + +KRATOS_CREATE_VARIABLE( Vector, UMAT_PARAMETERS ) + + +KRATOS_CREATE_VARIABLE(int, NUMBER_OF_UMAT_STATE_VARIABLES) +KRATOS_CREATE_VARIABLE(int, NUMBER_OF_UMAT_PARAMETERS) + +KRATOS_CREATE_VARIABLE( Vector, STATE_VARIABLES ) + +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_1 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_2 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_3 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_4 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_5 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_6 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_7 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_8 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_9 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_10 ) + +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_11 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_12 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_13 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_14 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_15 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_16 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_17 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_18 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_19 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_20 ) + +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_21 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_22 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_23 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_24 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_25 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_26 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_27 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_28 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_29 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_30 ) + +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_31 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_32 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_33 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_34 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_35 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_36 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_37 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_38 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_39 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_40 ) + +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_41 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_42 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_43 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_44 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_45 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_46 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_47 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_48 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_49 ) +KRATOS_CREATE_VARIABLE( double, STATE_VARIABLE_50 ) + +} diff --git a/applications/GeoMechanicsApplication/geo_mechanics_application_variables.h b/applications/GeoMechanicsApplication/geo_mechanics_application_variables.h new file mode 100644 index 000000000000..ea9e89c9d68a --- /dev/null +++ b/applications/GeoMechanicsApplication/geo_mechanics_application_variables.h @@ -0,0 +1,186 @@ +// KRATOS___ +// // ) ) +// // ___ ___ +// // ____ //___) ) // ) ) +// // / / // // / / +// ((____/ / ((____ ((___/ / MECHANICS +// +// License: geo_mechanics_application/license.txt +// +// Main authors: Vahid Galavi +// + +#if !defined(KRATOS_GEO_MECHANICS_APPLICATION_VARIABLES_H_INCLUDED ) +#define KRATOS_GEO_MECHANICS_APPLICATION_VARIABLES_H_INCLUDED + +// System includes + +// External includes + +// Project includes +#include "includes/define.h" +#include "includes/kratos_application.h" +#include "structural_mechanics_application_variables.h" +#include "geo_mechanics_application_constants.h" +#include + +namespace Kratos +{ + /* Variables from GeoMechanicsApplication */ + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, VELOCITY_COEFFICIENT ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, DT_PRESSURE_COEFFICIENT ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, DT_WATER_PRESSURE ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, NORMAL_FLUID_FLUX ) + + // K0 values + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, int, K0_MAIN_DIRECTION ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, K0_VALUE_XX ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, K0_VALUE_YY ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, K0_VALUE_ZZ ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, DENSITY_SOLID ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, BULK_MODULUS_SOLID ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, BULK_MODULUS_FLUID ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, PERMEABILITY_XX ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, PERMEABILITY_YY ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, PERMEABILITY_ZZ ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, PERMEABILITY_XY ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, PERMEABILITY_YZ ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, PERMEABILITY_ZX ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, MINIMUM_JOINT_WIDTH ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, TRANSVERSAL_PERMEABILITY ) + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS( GEO_MECHANICS_APPLICATION, FLUID_FLUX_VECTOR ) + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS( GEO_MECHANICS_APPLICATION, LOCAL_FLUID_FLUX_VECTOR ) + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS( GEO_MECHANICS_APPLICATION, LOCAL_STRESS_VECTOR ) + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS( GEO_MECHANICS_APPLICATION, LOCAL_RELATIVE_DISPLACEMENT_VECTOR ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Matrix, PERMEABILITY_MATRIX ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Matrix, LOCAL_PERMEABILITY_MATRIX ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, CRITICAL_DISPLACEMENT ) + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS( GEO_MECHANICS_APPLICATION, TOTAL_DISPLACEMENT ) + + KRATOS_DEFINE_APPLICATION_VARIABLE(GEO_MECHANICS_APPLICATION, bool, IS_CONVERGED) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Matrix, TOTAL_STRESS_TENSOR ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Vector, TOTAL_STRESS_VECTOR ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Matrix, CAUCHY_STRAIN_TENSOR ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Vector, CAUCHY_STRAIN_VECTOR ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, ARC_LENGTH_LAMBDA ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, ARC_LENGTH_RADIUS_FACTOR ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, TIME_UNIT_CONVERTER ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, LOCAL_EQUIVALENT_STRAIN ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, NONLOCAL_EQUIVALENT_STRAIN ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, JOINT_WIDTH ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, bool, NODAL_SMOOTHING ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Matrix, NODAL_CAUCHY_STRESS_TENSOR ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, NODAL_DAMAGE_VARIABLE ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, NODAL_JOINT_AREA ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, NODAL_JOINT_WIDTH ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, NODAL_JOINT_DAMAGE ) + + // Nodal load variables + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS( STRUCTURAL_MECHANICS_APPLICATION, POINT_LOAD ) + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS( STRUCTURAL_MECHANICS_APPLICATION, LINE_LOAD ) + KRATOS_DEFINE_3D_APPLICATION_VARIABLE_WITH_COMPONENTS( STRUCTURAL_MECHANICS_APPLICATION, SURFACE_LOAD ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, bool, RESET_DISPLACEMENTS ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, bool, CONSIDER_GEOMETRIC_STIFFNESS) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, bool, USE_CONSISTENT_MASS_MATRIX) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, bool, IGNORE_UNDRAINED ) + + // Retention models + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, SATURATED_SATURATION ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, RESIDUAL_SATURATION ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, VAN_GENUCHTEN_AIR_ENTRY_PRESSURE ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, VAN_GENUCHTEN_GN ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, VAN_GENUCHTEN_GL ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, MINIMUM_RELATIVE_PERMEABILITY ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, std::string, RETENTION_LAW ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, DEGREE_OF_SATURATION ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, EFFECTIVE_SATURATION ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, BISHOP_COEFICIENT ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, DERIVATIVE_OF_SATURATION ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, RELATIVE_PERMEABILITY ) + + // UDSM + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, std::string, UDSM_NAME ) // also for umat + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, int, UDSM_NUMBER ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, bool, IS_FORTRAN_UDSM ) // also for umat + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Vector, UMAT_PARAMETERS ) + + KRATOS_DEFINE_APPLICATION_VARIABLE(GEO_MECHANICS_APPLICATION, int, NUMBER_OF_UMAT_STATE_VARIABLES) + KRATOS_DEFINE_APPLICATION_VARIABLE(GEO_MECHANICS_APPLICATION, int, NUMBER_OF_UMAT_PARAMETERS) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, Vector, STATE_VARIABLES ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_1 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_2 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_3 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_4 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_5 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_6 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_7 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_8 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_9 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_10 ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_11 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_12 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_13 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_14 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_15 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_16 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_17 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_18 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_19 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_20 ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_21 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_22 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_23 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_24 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_25 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_26 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_27 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_28 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_29 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_30 ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_31 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_32 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_33 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_34 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_35 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_36 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_37 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_38 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_39 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_40 ) + + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_41 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_42 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_43 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_44 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_45 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_46 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_47 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_48 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_49 ) + KRATOS_DEFINE_APPLICATION_VARIABLE( GEO_MECHANICS_APPLICATION, double, STATE_VARIABLE_50 ) + +} + +#endif /* KRATOS_GEO_MECHANICS_APPLICATION_VARIABLES_H_INCLUDED */ diff --git a/applications/GeoMechanicsApplication/license.txt b/applications/GeoMechanicsApplication/license.txt new file mode 100644 index 000000000000..128a0064c3aa --- /dev/null +++ b/applications/GeoMechanicsApplication/license.txt @@ -0,0 +1,19 @@ +Kratos - GeoMechanics Application + +Copyright (c) 2021, Deltares, Vahid Galavi - All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the distribution. + - All advertising materials mentioning features or use of this software must display the following acknowledgement: + This product includes Kratos - GeoMechanics technology. + - Neither the name of the Deltares nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/applications/GeoMechanicsApplication/python_scripts/geomechanics_U_Pw_solver.py b/applications/GeoMechanicsApplication/python_scripts/geomechanics_U_Pw_solver.py new file mode 100644 index 000000000000..45dbf50aa90d --- /dev/null +++ b/applications/GeoMechanicsApplication/python_scripts/geomechanics_U_Pw_solver.py @@ -0,0 +1,459 @@ +# Importing the Kratos Library +import KratosMultiphysics +from KratosMultiphysics.python_solver import PythonSolver + +# Check that applications were imported in the main script +# DEPRECATION: "CheckRegisteredApplications" is not needed any more and can be safely removed +#KratosMultiphysics.CheckRegisteredApplications("GeoMechanicsApplication") + +# Import applications +import KratosMultiphysics.GeoMechanicsApplication as KratosGeo +import KratosMultiphysics.StructuralMechanicsApplication as KratosStructure + +# Import base class file +import KratosMultiphysics.GeoMechanicsApplication.geomechanics_solver as GeoSolver + +def CreateSolver(model, custom_settings): + return UPwSolver(model, custom_settings) + +class UPwSolver(GeoSolver.GeoMechanicalSolver): + '''Solver for the solution of displacement-pore pressure coupled problems.''' + + def __init__(self, model, custom_settings): + super(UPwSolver,self).__init__(model, custom_settings) + + # There is only a single rank in OpenMP, we always print + self._is_printing_rank = True + + + KratosMultiphysics.Logger.PrintInfo("UPwSolver", "Construction of UPwSolver finished.") + + @classmethod + def GetDefaultParameters(cls): + this_defaults = KratosMultiphysics.Parameters("""{ + "solver_type": "geomechanics_U_Pw_solver", + "model_part_name": "PorousDomain", + "domain_size": 2, + "start_time": 0.0, + "model_import_settings":{ + "input_type": "mdpa", + "input_filename": "unknown_name" + }, + "material_import_settings" :{ + "materials_filename": "" + }, + "time_stepping": { + "end_time" : 1.0, + "time_step": 0.1 + }, + "buffer_size": 2, + "echo_level": 0, + "reform_dofs_at_each_step": false, + "clear_storage": false, + "compute_reactions": false, + "move_mesh_flag": false, + "nodal_smoothing": false, + "reset_displacements": false, + "solution_type": "quasi_static", + "scheme_type": "Newmark", + "newmark_beta": 0.25, + "newmark_gamma": 0.5, + "newmark_theta": 0.5, + "rayleigh_m": 0.0, + "rayleigh_k": 0.0, + "strategy_type": "newton_raphson", + "convergence_criterion": "Displacement_criterion", + "displacement_relative_tolerance": 1.0e-4, + "displacement_absolute_tolerance": 1.0e-9, + "residual_relative_tolerance": 1.0e-4, + "residual_absolute_tolerance": 1.0e-9, + "desired_iterations" : 4, + "max_radius_factor" : 20.0, + "min_radius_factor" : 0.5, + "max_iterations" : 15, + "min_iterations" : 6, + "number_cycles" : 5, + "increase_factor" : 2.0, + "reduction_factor" : 0.5, + "realised_factor" : 1.0, + "calculate_reactions" : true, + "max_line_search_iterations" : 5, + "first_alpha_value" : 0.5, + "second_alpha_value" : 1.0, + "min_alpha" : 0.1, + "max_alpha" : 2.0, + "line_search_tolerance" : 0.5, + "rotation_dofs" : false, + "block_builder" : true, + "search_neighbours_step" : false, + "linear_solver_settings":{ + "solver_type": "AMGCL", + "tolerance": 1.0e-6, + "max_iteration": 100, + "scaling": false, + "verbosity": 0, + "preconditioner_type": "ILU0Preconditioner", + "smoother_type": "ilu0", + "krylov_type": "gmres", + "coarsening_type": "aggregation" + }, + "problem_domain_sub_model_part_list": [""], + "processes_sub_model_part_list": [""], + "body_domain_sub_model_part_list": [""], + "loads_sub_model_part_list": [], + "loads_variable_list": [] + }""") + + this_defaults.AddMissingParameters(super(UPwSolver, cls).GetDefaultParameters()) + return this_defaults + + def PrepareModelPart(self): + + # Set ProcessInfo variables + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.TIME, + self.settings["start_time"].GetDouble()) + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.DELTA_TIME, + self.settings["time_stepping"]["time_step"].GetDouble()) + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.STEP, 0) + + self.main_model_part.ProcessInfo.SetValue(KratosGeo.TIME_UNIT_CONVERTER, 1.0) + + self.main_model_part.ProcessInfo.SetValue(KratosGeo.NODAL_SMOOTHING, + self.settings["nodal_smoothing"].GetBool()) + + if not self.main_model_part.ProcessInfo[KratosMultiphysics.IS_RESTARTED]: + ## Executes the check and prepare model process (Create computing_model_part and set constitutive law) + self._ExecuteCheckAndPrepare() + ## Set buffer size + self._SetBufferSize() + + if not self.model.HasModelPart(self.settings["model_part_name"].GetString()): + self.model.AddModelPart(self.main_model_part) + + KratosMultiphysics.Logger.PrintInfo("UPwSolver", "Model reading finished.") + + def AddDofs(self): + ## displacement dofs + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,self.main_model_part) + + for node in self.main_model_part.Nodes: + # adding TOTAL_DISPLACEMENT as dofs + node.AddDof(KratosGeo.TOTAL_DISPLACEMENT_X) + node.AddDof(KratosGeo.TOTAL_DISPLACEMENT_Y) + node.AddDof(KratosGeo.TOTAL_DISPLACEMENT_Z) + + ## Fluid dofs + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.WATER_PRESSURE, KratosMultiphysics.REACTION_WATER_PRESSURE,self.main_model_part) + + if self.settings["rotation_dofs"].GetBool(): + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ROTATION_X, KratosMultiphysics.REACTION_MOMENT_X,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ROTATION_Y, KratosMultiphysics.REACTION_MOMENT_Y,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ROTATION_Z, KratosMultiphysics.REACTION_MOMENT_Z,self.main_model_part) + + if (self.settings["solution_type"].GetString() == "Dynamic"): + KratosMultiphysics.Logger.PrintInfo("UPwSolver", "Dynamic analysis.") + for node in self.main_model_part.Nodes: + # adding VELOCITY as dofs + node.AddDof(KratosMultiphysics.VELOCITY_X) + node.AddDof(KratosMultiphysics.VELOCITY_Y) + node.AddDof(KratosMultiphysics.VELOCITY_Z) + # adding ACCELERATION as dofs + node.AddDof(KratosMultiphysics.ACCELERATION_X) + node.AddDof(KratosMultiphysics.ACCELERATION_Y) + node.AddDof(KratosMultiphysics.ACCELERATION_Z) + # if self.settings["rotation_dofs"].GetBool(): + # for node in self.main_model_part.Nodes: + # # adding ANGULAR_VELOCITY as dofs + # node.AddDof(KratosMultiphysics.ANGULAR_VELOCITY_X) + # node.AddDof(KratosMultiphysics.ANGULAR_VELOCITY_Y) + # node.AddDof(KratosMultiphysics.ANGULAR_VELOCITY_Z) + # # adding ANGULAR_ACCELERATION as dofs + # node.AddDof(KratosMultiphysics.ANGULAR_ACCELERATION_X) + # node.AddDof(KratosMultiphysics.ANGULAR_ACCELERATION_Y) + # node.AddDof(KratosMultiphysics.ANGULAR_ACCELERATION_Z) + + KratosMultiphysics.Logger.PrintInfo("UPwSolver", "DOFs added correctly.") + + + def Initialize(self): + KratosMultiphysics.Logger.PrintInfo("::[GeoMechanics_U_Pw_Solver]:: ", "Initialisation ...") + + self.computing_model_part = self.GetComputingModelPart() + + # Fill the previous steps of the buffer with the initial conditions + self._FillBuffer() + + # Construct the linear solver + self.linear_solver = self._ConstructLinearSolver() + + # Builder and solver creation + builder_and_solver = self._ConstructBuilderAndSolver(self.settings["block_builder"].GetBool()) + + # Solution scheme creation + self.scheme = self._ConstructScheme(self.settings["scheme_type"].GetString(), + self.settings["solution_type"].GetString()) + + # Get the convergence criterion + self.convergence_criterion = self._ConstructConvergenceCriterion(self.settings["convergence_criterion"].GetString()) + + # Solver creation + self.solver = self._ConstructSolver(builder_and_solver, + self.settings["strategy_type"].GetString()) + + # Set echo_level + self.SetEchoLevel(self.settings["echo_level"].GetInt()) + + # Initialize Strategy + if self.settings["clear_storage"].GetBool(): + self.Clear() + + self.solver.Initialize() + + KratosMultiphysics.Logger.PrintInfo("UPwSolver", "solver.Initialize is set successfully") + + # Check if everything is assigned correctly + self.Check() + + KratosMultiphysics.Logger.PrintInfo("UPwSolver", "Solver initialization finished.") + + def InitializeSolutionStep(self): + self.solver.InitializeSolutionStep() + + def Predict(self): + self.solver.Predict() + + def SolveSolutionStep(self): + is_converged = self.solver.SolveSolutionStep() + return is_converged + + def FinalizeSolutionStep(self): + self.solver.FinalizeSolutionStep() + + #### Specific internal functions #### + + def _ExecuteCheckAndPrepare(self): + + self.computing_model_part_name = "porous_computational_model_part" + + # Create list of sub sub model parts (it is a copy of the standard lists with a different name) + import json + + self.body_domain_sub_sub_model_part_list = [] + for i in range(self.settings["body_domain_sub_model_part_list"].size()): + self.body_domain_sub_sub_model_part_list.append("sub_"+self.settings["body_domain_sub_model_part_list"][i].GetString()) + self.body_domain_sub_sub_model_part_list = KratosMultiphysics.Parameters(json.dumps(self.body_domain_sub_sub_model_part_list)) + + self.loads_sub_sub_model_part_list = [] + for i in range(self.settings["loads_sub_model_part_list"].size()): + self.loads_sub_sub_model_part_list.append("sub_"+self.settings["loads_sub_model_part_list"][i].GetString()) + self.loads_sub_sub_model_part_list = KratosMultiphysics.Parameters(json.dumps(self.loads_sub_sub_model_part_list)) + + # Auxiliary parameters object for the CheckAndPepareModelProcess + params = KratosMultiphysics.Parameters("{}") + params.AddEmptyValue("computing_model_part_name").SetString(self.computing_model_part_name) + params.AddValue("problem_domain_sub_model_part_list",self.settings["problem_domain_sub_model_part_list"]) + params.AddValue("processes_sub_model_part_list",self.settings["processes_sub_model_part_list"]) + params.AddValue("body_domain_sub_model_part_list",self.settings["body_domain_sub_model_part_list"]) + params.AddValue("body_domain_sub_sub_model_part_list",self.body_domain_sub_sub_model_part_list) + params.AddValue("loads_sub_model_part_list",self.settings["loads_sub_model_part_list"]) + params.AddValue("loads_sub_sub_model_part_list",self.loads_sub_sub_model_part_list) + # CheckAndPrepareModelProcess creates the porous_computational_model_part + from KratosMultiphysics.GeoMechanicsApplication import check_and_prepare_model_process_geo + check_and_prepare_model_process_geo.CheckAndPrepareModelProcess(self.main_model_part, params).Execute() + + # Constitutive law import + + # This will be removed once the Model is fully supported! => It wont be necessary any more + # NOTE: We do this here in case the model is empty, so the properties can be assigned + if not self.model.HasModelPart(self.main_model_part.Name): + self.model.AddModelPart(self.main_model_part) + + # Import constitutive laws. + materials_imported = self.import_constitutive_laws() + if materials_imported: + KratosMultiphysics.Logger.PrintInfo("::[GeoMechanicalSolver]:: ", "Constitutive law was successfully imported.") + else: + # KratosMultiphysics.Logger.PrintInfo("::[GeoMechanicalSolver]:: ", "Constitutive law was not imported.") + raise Exception("::[GeoMechanicalSolver]:: ", "Constitutive law was not imported.") + + def _SetBufferSize(self): + required_buffer_size = self.settings["buffer_size"].GetInt() + if required_buffer_size < self.GetMinimumBufferSize(): + required_buffer_size = self.GetMinimumBufferSize() + current_buffer_size = self.main_model_part.GetBufferSize() + buffer_size = max(current_buffer_size, required_buffer_size) + self.main_model_part.SetBufferSize(buffer_size) + + def _FillBuffer(self): + buffer_size = self.main_model_part.GetBufferSize() + time = self.main_model_part.ProcessInfo[KratosMultiphysics.TIME] + delta_time = self.main_model_part.ProcessInfo[KratosMultiphysics.DELTA_TIME] + step = self.main_model_part.ProcessInfo[KratosMultiphysics.STEP] + + step = step - (buffer_size-1)*1 + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.STEP, step) + time = time - (buffer_size-1)*delta_time + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.TIME, time) + for i in range(buffer_size-1): + step = step + 1 + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.STEP, step) + time = time + delta_time + self.main_model_part.CloneTimeStep(time) + + def _ConstructLinearSolver(self): + import KratosMultiphysics.python_linear_solver_factory as linear_solver_factory + return linear_solver_factory.ConstructSolver(self.settings["linear_solver_settings"]) + + def _ConstructBuilderAndSolver(self, block_builder): + + # Creating the builder and solver + if (block_builder): + builder_and_solver = KratosMultiphysics.ResidualBasedBlockBuilderAndSolver(self.linear_solver) + else: + builder_and_solver = KratosMultiphysics.ResidualBasedEliminationBuilderAndSolver(self.linear_solver) + + return builder_and_solver + + def _ConstructScheme(self, scheme_type, solution_type): + + self.main_model_part.ProcessInfo.SetValue(KratosGeo.VELOCITY_COEFFICIENT, 1.0) + self.main_model_part.ProcessInfo.SetValue(KratosGeo.DT_PRESSURE_COEFFICIENT, 1.0) + + if (scheme_type == "Newmark"): + beta = self.settings["newmark_beta"].GetDouble() + gamma = self.settings["newmark_gamma"].GetDouble() + theta = self.settings["newmark_theta"].GetDouble() + rayleigh_m = self.settings["rayleigh_m"].GetDouble() + rayleigh_k = self.settings["rayleigh_k"].GetDouble() + self.main_model_part.ProcessInfo.SetValue(KratosStructure.RAYLEIGH_ALPHA, rayleigh_m) + self.main_model_part.ProcessInfo.SetValue(KratosStructure.RAYLEIGH_BETA, rayleigh_k) + KratosMultiphysics.Logger.PrintInfo("UPwSolver, solution_type", solution_type) + if (solution_type.lower() == "quasi-static" or solution_type.lower() == "quasi_static"): + if (rayleigh_m < 1.0e-20 and rayleigh_k < 1.0e-20): + KratosMultiphysics.Logger.PrintInfo("UPwSolver, scheme", "Quasi-UnDamped.") + scheme = KratosGeo.NewmarkQuasistaticUPwScheme(beta,gamma,theta) + else: + KratosMultiphysics.Logger.PrintInfo("UPwSolver, scheme", "Quasi-Damped.") + scheme = KratosGeo.NewmarkQuasistaticDampedUPwScheme(beta,gamma,theta) + elif (solution_type.lower() == "dynamic"): + KratosMultiphysics.Logger.PrintInfo("UPwSolver, scheme", "Dynamic.") + scheme = KratosGeo.NewmarkDynamicUPwScheme(beta,gamma,theta) + elif (solution_type.lower() == "k0-procedure" or solution_type.lower() == "k0_procedure"): + if (rayleigh_m < 1.0e-20 and rayleigh_k < 1.0e-20): + KratosMultiphysics.Logger.PrintInfo("UPwSolver, scheme", "Quasi-UnDamped.") + scheme = KratosGeo.NewmarkQuasistaticUPwScheme(beta,gamma,theta) + else: + KratosMultiphysics.Logger.PrintInfo("UPwSolver, scheme", "Quasi-Damped.") + scheme = KratosGeo.NewmarkQuasistaticDampedUPwScheme(beta,gamma,theta) + else: + raise Exception("Undefined solution type", solution_type) + else: + raise Exception("Apart from Newmark, other scheme_type are not available.") + + return scheme + + def _ConstructConvergenceCriterion(self, convergence_criterion): + + D_RT = self.settings["displacement_relative_tolerance"].GetDouble() + D_AT = self.settings["displacement_absolute_tolerance"].GetDouble() + R_RT = self.settings["residual_relative_tolerance"].GetDouble() + R_AT = self.settings["residual_absolute_tolerance"].GetDouble() + echo_level = self.settings["echo_level"].GetInt() + + if(convergence_criterion == "Displacement_criterion" or convergence_criterion == "displacement_criterion"): + convergence_criterion = KratosMultiphysics.DisplacementCriteria(D_RT, D_AT) + convergence_criterion.SetEchoLevel(echo_level) + elif(convergence_criterion == "Residual_criterion" or convergence_criterion == "residual_criterion"): + convergence_criterion = KratosMultiphysics.ResidualCriteria(R_RT, R_AT) + convergence_criterion.SetEchoLevel(echo_level) + elif(convergence_criterion == "And_criterion" or convergence_criterion == "and_criterion"): + Displacement = KratosMultiphysics.DisplacementCriteria(D_RT, D_AT) + Displacement.SetEchoLevel(echo_level) + Residual = KratosMultiphysics.ResidualCriteria(R_RT, R_AT) + Residual.SetEchoLevel(echo_level) + convergence_criterion = KratosMultiphysics.AndCriteria(Residual, Displacement) + elif(convergence_criterion == "Or_criterion" or convergence_criterion == "or_criterion"): + Displacement = KratosMultiphysics.DisplacementCriteria(D_RT, D_AT) + Displacement.SetEchoLevel(echo_level) + Residual = KratosMultiphysics.ResidualCriteria(R_RT, R_AT) + Residual.SetEchoLevel(echo_level) + convergence_criterion = KratosMultiphysics.OrCriteria(Residual, Displacement) + + return convergence_criterion + + def _ConstructSolver(self, builder_and_solver, strategy_type): + + self.main_model_part.ProcessInfo.SetValue(KratosGeo.IS_CONVERGED, True) + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.NL_ITERATION_NUMBER, 1) + + max_iters = self.settings["max_iterations"].GetInt() + compute_reactions = self.settings["compute_reactions"].GetBool() + reform_step_dofs = self.settings["reform_dofs_at_each_step"].GetBool() + move_mesh_flag = self.settings["move_mesh_flag"].GetBool() + + if strategy_type == "newton_raphson": + self.strategy_params = KratosMultiphysics.Parameters("{}") + self.strategy_params.AddValue("loads_sub_model_part_list",self.loads_sub_sub_model_part_list) + self.strategy_params.AddValue("loads_variable_list",self.settings["loads_variable_list"]) + solving_strategy = KratosGeo.GeoMechanicsNewtonRaphsonStrategy(self.computing_model_part, + self.scheme, + self.linear_solver, + self.convergence_criterion, + builder_and_solver, + self.strategy_params, + max_iters, + compute_reactions, + reform_step_dofs, + move_mesh_flag) + elif strategy_type == "line_search": + self.strategy_params = KratosMultiphysics.Parameters("{}") + self.strategy_params.AddValue("max_iteration", self.settings["max_iterations"]) + self.strategy_params.AddValue("compute_reactions", self.settings["compute_reactions"]) + self.strategy_params.AddValue("max_line_search_iterations", self.settings["max_line_search_iterations"]) + self.strategy_params.AddValue("first_alpha_value", self.settings["first_alpha_value"]) + self.strategy_params.AddValue("second_alpha_value", self.settings["second_alpha_value"]) + self.strategy_params.AddValue("min_alpha", self.settings["min_alpha"]) + self.strategy_params.AddValue("max_alpha", self.settings["max_alpha"]) + self.strategy_params.AddValue("line_search_tolerance", self.settings["line_search_tolerance"]) + solving_strategy = KratosMultiphysics.LineSearchStrategy(self.computing_model_part, + self.scheme, + self.linear_solver, + self.convergence_criterion, + self.strategy_params) + + elif strategy_type == "arc_length": + # Arc-Length strategy + self.main_model_part.ProcessInfo.SetValue(KratosGeo.ARC_LENGTH_LAMBDA, 1.0) + self.main_model_part.ProcessInfo.SetValue(KratosGeo.ARC_LENGTH_RADIUS_FACTOR, 1.0) + self.strategy_params = KratosMultiphysics.Parameters("{}") + self.strategy_params.AddValue("desired_iterations",self.settings["desired_iterations"]) + self.strategy_params.AddValue("max_radius_factor",self.settings["max_radius_factor"]) + self.strategy_params.AddValue("min_radius_factor",self.settings["min_radius_factor"]) + self.strategy_params.AddValue("loads_sub_model_part_list",self.loads_sub_sub_model_part_list) + self.strategy_params.AddValue("loads_variable_list",self.settings["loads_variable_list"]) + solving_strategy = KratosGeo.GeoMechanicsRammArcLengthStrategy(self.computing_model_part, + self.scheme, + self.linear_solver, + self.convergence_criterion, + builder_and_solver, + self.strategy_params, + max_iters, + compute_reactions, + reform_step_dofs, + move_mesh_flag) + else: + raise Exception("Undefined strategy type", strategy_type) + + return solving_strategy + + def _CheckConvergence(self): + + IsConverged = self.solver.IsConverged() + + return IsConverged + + def _UpdateLoads(self): + + self.solver.UpdateLoads() diff --git a/applications/GeoMechanicsApplication/python_scripts/geomechanics_analysis.py b/applications/GeoMechanicsApplication/python_scripts/geomechanics_analysis.py new file mode 100644 index 000000000000..2f1ac07074be --- /dev/null +++ b/applications/GeoMechanicsApplication/python_scripts/geomechanics_analysis.py @@ -0,0 +1,223 @@ +import time as timer +import os +import sys + +sys.path.append(os.path.join('..','..','..')) + +import KratosMultiphysics as Kratos +import KratosMultiphysics.LinearSolversApplication +import KratosMultiphysics.StructuralMechanicsApplication +import KratosMultiphysics.GeoMechanicsApplication as KratosGeo + +from KratosMultiphysics.analysis_stage import AnalysisStage +from KratosMultiphysics.GeoMechanicsApplication import geomechanics_solvers_wrapper + +from importlib import import_module + +class GeoMechanicsAnalysisBase(AnalysisStage): + '''Main script for geomechanics simulations.''' + + def __init__(self,model,parameters): + # Time monitoring + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(),timer.ctime()) + self.initial_time = timer.perf_counter() + + # Set number of OMP threads + parallel=Kratos.OpenMPUtils() + problem_data_settings = parameters["problem_data"] + if problem_data_settings.Has("number_of_threads"): + parallel.SetNumThreads(parameters["problem_data"]["number_of_threads"].GetInt()) + else: + parallel.SetNumThreads(1) + + ## Import parallel modules if needed + if (parameters["problem_data"]["parallel_type"].GetString() == "MPI"): + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(),"MPI parallel configuration. OMP_NUM_THREADS =",parallel.GetNumThreads()) + else: + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(),"OpenMP parallel configuration. OMP_NUM_THREADS =",parallel.GetNumThreads()) + + # Creating solver and model part and adding variables + super().__init__(model,parameters) + + def _CreateSolver(self): + solver = geomechanics_solvers_wrapper.CreateSolver(self.model, self.project_parameters) + return solver + + def _GetOrderOfProcessesInitialization(self): + return ["constraints_process_list", + "loads_process_list", + "auxiliar_process_list"] + + def _GetSimulationName(self): + return "GeoMechanics Analysis" + + def _CalculateTotalDisplacement(self,node, old_total_displacement): + """ + Calculates total displacement + :param node: + :return: + """ + stage_displacement = node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT) + total_displacement = old_total_displacement + stage_displacement + node.SetSolutionStepValue(KratosGeo.TOTAL_DISPLACEMENT, total_displacement) + + def Initialize(self): + super(GeoMechanicsAnalysisBase,self).Initialize() + if (self.reset_displacements): + self._GetSolver().main_model_part.ProcessInfo[KratosGeo.RESET_DISPLACEMENTS] = True + KratosMultiphysics.VariableUtils().SetHistoricalVariableToZero(KratosMultiphysics.DISPLACEMENT,self._GetSolver().GetComputingModelPart().Nodes) + KratosMultiphysics.VariableUtils().SetHistoricalVariableToZero(KratosMultiphysics.ROTATION,self._GetSolver().GetComputingModelPart().Nodes) + + for node in self._GetSolver().GetComputingModelPart().Nodes: + dNew = node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT,0) + node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT, 1, dNew) + rotNew = node.GetSolutionStepValue(KratosMultiphysics.ROTATION,0) + node.SetSolutionStepValue(KratosMultiphysics.ROTATION, 1, rotNew) + + KratosMultiphysics.VariableUtils().UpdateCurrentToInitialConfiguration(self._GetSolver().GetComputingModelPart().Nodes) + + else: + self._GetSolver().main_model_part.ProcessInfo[KratosGeo.RESET_DISPLACEMENTS] = False + + def Finalize(self): + super(GeoMechanicsAnalysisBase,self).Finalize() + + # Finalizing strategy + if self.parallel_type == "OpenMP": + self._GetSolver().Clear() + + # Time control + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(),"Analysis Completed. Elapsed Time = %.3f" % (timer.perf_counter() - self.initial_time)," seconds.") + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(),timer.ctime()) + + def KeepAdvancingSolutionLoop(self): + return self._GetSolver().KeepAdvancingSolutionLoop(self.end_time) + + def PrintAnalysisStageProgressInformation(self): + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "STEP: ", self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.STEP]) + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "TIME: ", self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.TIME]) + +class GeoMechanicsAnalysis(GeoMechanicsAnalysisBase): + + def __init__(self, model, project_parameters): + super(GeoMechanicsAnalysis, self).__init__(model, project_parameters) + + self.reduction_factor = project_parameters["solver_settings"]["reduction_factor"].GetDouble() + self.increase_factor = project_parameters["solver_settings"]["increase_factor"].GetDouble() + self.delta_time = project_parameters["solver_settings"]["time_stepping"]["time_step"].GetDouble() + + self.max_delta_time_factor = 1000.0 + if project_parameters["solver_settings"]["time_stepping"].Has("max_delta_time_factor"): + self.max_delta_time_factor = \ + project_parameters["solver_settings"]["time_stepping"]["max_delta_time_factor"].GetDouble() + + self.max_delta_time = self.delta_time * self.max_delta_time_factor + self.max_iterations = project_parameters["solver_settings"]["max_iterations"].GetInt() + self.min_iterations = project_parameters["solver_settings"]["min_iterations"].GetInt() + self.number_cycles = project_parameters["solver_settings"]["number_cycles"].GetInt() + self.solution_type = project_parameters["solver_settings"]["solution_type"].GetString() + self.reset_displacements = project_parameters["solver_settings"]["reset_displacements"].GetBool() + + def FinalizeSolutionStep(self): + super().FinalizeSolutionStep() + + if(self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.NL_ITERATION_NUMBER] > self.max_iterations): + raise Exception("max_number_of_iterations_exceeded") + + def RunSolutionLoop(self): + """This function executes the solution loop of the AnalysisStage + It can be overridden by derived classes + """ + if self._GetSolver().settings["reset_displacements"].GetBool(): + old_total_displacements = [node.GetSolutionStepValue(KratosGeo.TOTAL_DISPLACEMENT) + for node in self._GetSolver().GetComputingModelPart().Nodes] + + while self.KeepAdvancingSolutionLoop(): + if(self.delta_time > self.max_delta_time): + self.delta_time = self.max_delta_time + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "reducing delta_time to max_delta_time: ", self.max_delta_time) + t = self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.TIME] + new_time = t + self.delta_time + if (new_time > self.end_time): + new_time = self.end_time + self.delta_time = new_time - t + self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.STEP] += 1 + self._GetSolver().main_model_part.CloneTimeStep(new_time) + self._GetSolver().main_model_part.ProcessInfo[KratosMultiphysics.START_TIME] = self.time + self._GetSolver().main_model_part.ProcessInfo[KratosMultiphysics.END_TIME] = self.end_time + + converged = False + number_cycle = 0 + while (not converged and number_cycle < self.number_cycles): + + number_cycle +=1 + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "cycle: ", number_cycle) + t = self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.TIME] + corrected_time = t - self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.DELTA_TIME] + self.delta_time + self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.TIME] = corrected_time + self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.DELTA_TIME] = self.delta_time + + self.InitializeSolutionStep() + self._GetSolver().Predict() + converged = self._GetSolver().SolveSolutionStep() + + if (self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.NL_ITERATION_NUMBER] >= self.max_iterations or not converged): + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "Down-scaling with factor: ", self.reduction_factor) + self.delta_time *= self.reduction_factor + + #converged = False + # Reset displacements to the initial + KratosMultiphysics.VariableUtils().UpdateCurrentPosition(self._GetSolver().GetComputingModelPart().Nodes, KratosMultiphysics.DISPLACEMENT,1) + for node in self._GetSolver().GetComputingModelPart().Nodes: + dold = node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT,1) + node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT,0,dold) + + # for node in self._GetSolver().GetComputingModelPart().Nodes: + # # adding TOTAL_DISPLACEMENT as dofs + # KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "DISPLACEMENT_0: ", node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT)) + # KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "DISPLACEMENT_1: ", node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT,1)) + + elif (self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.NL_ITERATION_NUMBER] < self.min_iterations): + KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "Up-scaling with factor: ", self.increase_factor) + #converged = True + self.delta_time *= self.increase_factor + t = self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.TIME] + corrected_time = t + self.delta_time + if (corrected_time > self.end_time): + corrected_time = self.end_time + self.delta_time = corrected_time - t + + if self._GetSolver().settings["reset_displacements"].GetBool() and converged: + for idx, node in enumerate(self._GetSolver().GetComputingModelPart().Nodes): + self._CalculateTotalDisplacement(node, old_total_displacements[idx]) + + if (not converged): + raise Exception('The maximum number of cycles is reached without convergence!') + + self.FinalizeSolutionStep() + self.OutputSolutionStep() + + +if __name__ == '__main__': + from sys import argv + + if len(argv) > 2: + err_msg = 'Too many input arguments!\n' + err_msg += 'Use this script in the following way:\n' + err_msg += '- With default parameter file (assumed to be called "ProjectParameters.json"):\n' + err_msg += ' "python geomechanics_analysis.py"\n' + err_msg += '- With custom parameter file:\n' + err_msg += ' "python geomechanics_analysis.py .json"\n' + raise Exception(err_msg) + + if len(argv) == 2: # ProjectParameters is being passed from outside + parameter_file_name = argv[1] + else: # using default name + parameter_file_name = "ProjectParameters.json" + + with open(parameter_file_name,'r') as parameter_file: + parameters = Kratos.Parameters(parameter_file.read()) + + model = Kratos.Model() + simulation = GeoMechanicsAnalysis(model,parameters) + simulation.Run() diff --git a/applications/GeoMechanicsApplication/python_scripts/geomechanics_solver.py b/applications/GeoMechanicsApplication/python_scripts/geomechanics_solver.py new file mode 100644 index 000000000000..e87d6202ba35 --- /dev/null +++ b/applications/GeoMechanicsApplication/python_scripts/geomechanics_solver.py @@ -0,0 +1,230 @@ +# Importing the Kratos Library +import KratosMultiphysics +from KratosMultiphysics.python_solver import PythonSolver + +# Import applications +import KratosMultiphysics.StructuralMechanicsApplication as StructuralMechanicsApplication +import KratosMultiphysics.GeoMechanicsApplication as GeoMechanicsApplication + +def CreateSolver(model, custom_settings): + return GeoMechanicalSolver(model, custom_settings) + +class GeoMechanicalSolver(PythonSolver): + """The base class for geomechanics solvers. + + This class provides shared functions for importing and exporting models, + adding nodal variables and dofs and solving each solution step. + + Derived classes can override the functions + """ + def __init__(self, model, custom_settings): + + super().__init__(model, custom_settings) + + # # Overwrite the default settings with user-provided parameters. + # self.settings.ValidateAndAssignDefaults(default_settings) + model_part_name = self.settings["model_part_name"].GetString() + + if model_part_name == "": + raise Exception('Please specify a model_part name!') + + # This will be changed once the Model is fully supported! + if self.model.HasModelPart(model_part_name): + self.main_model_part = self.model[model_part_name] + self.solver_imports_model_part = False + else: + self.main_model_part = self.model.CreateModelPart(model_part_name) + + domain_size = self.settings["domain_size"].GetInt() + if domain_size < 0: + raise Exception('Please specify a "domain_size" >= 0!') + + self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.DOMAIN_SIZE, domain_size) + self.solver_imports_model_part = True + + self.min_buffer_size = 2 + + KratosMultiphysics.Logger.PrintInfo("::[GeoMechanicalSolver]:: ", "Construction finished") + + # Set if the analysis is restarted + if self.settings["model_import_settings"]["input_type"].GetString() == "rest": + KratosMultiphysics.Logger.PrintInfo("geomechanics_solver", "is a restarted model") + self.main_model_part.ProcessInfo[KratosMultiphysics.IS_RESTARTED] = True + else: + KratosMultiphysics.Logger.PrintInfo("geomechanics_solver", "is not a restarted model") + self.main_model_part.ProcessInfo[KratosMultiphysics.IS_RESTARTED] = False + + def AddVariables(self): + # this can safely be called also for restarts, it is internally checked if the variables exist already + # Variables for 1-phase types of calculations: + # Add displacements. + self._add_displacement_variables() + + # Add rotational variables + self._add_rotational_variables() + + # Add dynamic variables + self._add_dynamic_variables() + + # Variables for 2-phase types of calculations: + ## Fluid Variables + self._add_water_variables() + + ## smoothing variables + self._add_smoothing_variables() + + # Add variables that the user defined in the ProjectParameters + if (self.settings.Has("auxiliary_variables_list")): + for i in range(self.settings["auxiliary_variables_list"].size()): + variable_name = self.settings["auxiliary_variables_list"][i].GetString() + variable = KratosMultiphysics.KratosGlobals.GetVariable(variable_name) + self.main_model_part.AddNodalSolutionStepVariable(variable) + + KratosMultiphysics.Logger.PrintInfo("::[GeoMechanicalSolver]:: ", "Variables ADDED") + + def AddDofs(self): + pass + + def GetMinimumBufferSize(self): + return self.min_buffer_size + + def ImportModelPart(self): + """This function imports the ModelPart + """ + if self.solver_imports_model_part: + self._ImportModelPart(self.main_model_part, self.settings["model_import_settings"]) + + def PrepareModelPart(self): + """This function prepares the ModelPart for being used by the PythonSolver + """ + pass + + def KeepAdvancingSolutionLoop(self, end_time): + current_time_corrected = self.main_model_part.ProcessInfo[KratosMultiphysics.TIME] + return current_time_corrected < end_time + + def Initialize(self): + """Perform initialization after adding nodal variables and dofs to the main model part. """ + pass + + def InitializeSolutionStep(self): + pass + + def Predict(self): + pass + + def SolveSolutionStep(self): + pass + + def FinalizeSolutionStep(self): + pass + + def AdvanceInTime(self, current_time): + dt = self.ComputeDeltaTime() + current_time_corrected = self.main_model_part.ProcessInfo[KratosMultiphysics.TIME] + new_time = current_time_corrected + dt + self.main_model_part.CloneTimeStep(new_time) + self.main_model_part.ProcessInfo[KratosMultiphysics.STEP] += 1 + + return new_time + + def ComputeDeltaTime(self): + return self.main_model_part.ProcessInfo[KratosMultiphysics.DELTA_TIME] + + def GetComputingModelPart(self): + return self.main_model_part.GetSubModelPart(self.computing_model_part_name) + + def ExportModelPart(self): + name_out_file = self.settings["model_import_settings"]["input_filename"].GetString()+".out" + file = open(name_out_file + ".mdpa","w") + file.close() + KratosMultiphysics.ModelPartIO(name_out_file, KratosMultiphysics.IO.WRITE).WriteModelPart(self.main_model_part) + + def SetEchoLevel(self, level): + self.solver.SetEchoLevel(level) + + def Clear(self): + self.solver.Clear() + + def Check(self): + self.solver.Check() + + + #### Specific internal functions #### + + def import_constitutive_laws(self): + materials_filename = self.settings["material_import_settings"]["materials_filename"].GetString() + KratosMultiphysics.Logger.PrintInfo("::[GeoMechanicalSolver]:: importing constitutive law", materials_filename) + if (materials_filename != ""): + # Add constitutive laws and material properties from json file to model parts. + material_settings = KratosMultiphysics.Parameters("""{"Parameters": {"materials_filename": ""}} """) + material_settings["Parameters"]["materials_filename"].SetString(materials_filename) + KratosMultiphysics.ReadMaterialsUtility(material_settings, self.model) + materials_imported = True + else: + materials_imported = False + return materials_imported + + #### Private functions #### + + def _add_dynamic_variables(self): + # For being consistent for Serial and Trilinos + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VELOCITY) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.ACCELERATION) + + def _add_displacement_variables(self): + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.DISPLACEMENT) + self.main_model_part.AddNodalSolutionStepVariable(GeoMechanicsApplication.TOTAL_DISPLACEMENT) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.REACTION) + self.main_model_part.AddNodalSolutionStepVariable(StructuralMechanicsApplication.POINT_LOAD) + self.main_model_part.AddNodalSolutionStepVariable(StructuralMechanicsApplication.LINE_LOAD) + self.main_model_part.AddNodalSolutionStepVariable(StructuralMechanicsApplication.SURFACE_LOAD) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VOLUME_ACCELERATION) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NORMAL_CONTACT_STRESS) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.TANGENTIAL_CONTACT_STRESS) + + def _add_rotational_variables(self): + if (self.settings.Has("rotation_dofs")): + if self.settings["rotation_dofs"].GetBool(): + # Add specific variables for the problem (rotation dofs). + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.ROTATION) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.REACTION_MOMENT) + self.main_model_part.AddNodalSolutionStepVariable(StructuralMechanicsApplication.POINT_MOMENT) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.ANGULAR_VELOCITY) + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.ANGULAR_ACCELERATION) + + def _add_water_variables(self): + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.WATER_PRESSURE) + # Add reactions for the water pressure + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.REACTION_WATER_PRESSURE) + # Add dynamic variables + self.main_model_part.AddNodalSolutionStepVariable(GeoMechanicsApplication.DT_WATER_PRESSURE) + # Add variables for the water conditions + self.main_model_part.AddNodalSolutionStepVariable(GeoMechanicsApplication.NORMAL_FLUID_FLUX) + + def _add_smoothing_variables(self): + if (self.settings.Has("nodal_smoothing")): + if(self.settings["nodal_smoothing"].GetBool() == True): + self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NODAL_AREA) + self.main_model_part.AddNodalSolutionStepVariable(GeoMechanicsApplication.NODAL_CAUCHY_STRESS_TENSOR) + self.main_model_part.AddNodalSolutionStepVariable(GeoMechanicsApplication.NODAL_DAMAGE_VARIABLE) + self.main_model_part.AddNodalSolutionStepVariable(GeoMechanicsApplication.NODAL_JOINT_AREA) + self.main_model_part.AddNodalSolutionStepVariable(GeoMechanicsApplication.NODAL_JOINT_WIDTH) + self.main_model_part.AddNodalSolutionStepVariable(GeoMechanicsApplication.NODAL_JOINT_DAMAGE) + + def _add_dynamic_dofs(self): + # For being consistent for Serial and Trilinos + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.VELOCITY_X,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.VELOCITY_Y,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.VELOCITY_Z,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ACCELERATION_X,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ACCELERATION_Y,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ACCELERATION_Z,self.main_model_part) + if(self.settings["rotation_dofs"].GetBool()): + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ANGULAR_VELOCITY_X,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ANGULAR_VELOCITY_Y,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ANGULAR_VELOCITY_Z,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ANGULAR_ACCELERATION_X,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ANGULAR_ACCELERATION_Y,self.main_model_part) + KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.ANGULAR_ACCELERATION_Z,self.main_model_part) + diff --git a/applications/GeoMechanicsApplication/python_scripts/geomechanics_solvers_wrapper.py b/applications/GeoMechanicsApplication/python_scripts/geomechanics_solvers_wrapper.py new file mode 100644 index 000000000000..568b74105235 --- /dev/null +++ b/applications/GeoMechanicsApplication/python_scripts/geomechanics_solvers_wrapper.py @@ -0,0 +1,60 @@ +import KratosMultiphysics +from importlib import import_module + +def CreateSolver(model, custom_settings): + + if (type(model) != KratosMultiphysics.Model): + raise Exception("input is expected to be provided as a Kratos Model object") + + if (type(custom_settings) != KratosMultiphysics.Parameters): + raise Exception("input is expected to be provided as a Kratos Parameters object") + + parallelism = custom_settings["problem_data"]["parallel_type"].GetString() + solver_type = custom_settings["solver_settings"]["solver_type"].GetString() + + # Solvers for OpenMP parallelism + if (parallelism == "OpenMP"): + if (solver_type.lower() == "dynamic"): + time_integration_method = custom_settings["solver_settings"]["time_integration_method"].GetString() + if (time_integration_method == "implicit"): + solver_module_name = "geomechanics_implicit_dynamic_solver" + elif ( time_integration_method == "explicit"): + solver_module_name = "geomechanics_explicit_dynamic_solver" + else: + err_msg = "The requested time integration method \"" + time_integration_method + "\" is not in the python solvers wrapper\n" + err_msg += "Available options are: \"implicit\", \"explicit\"" + raise Exception(err_msg) + + elif (solver_type.lower() == "u_pw" or solver_type.lower() == "geomechanics_u_pw_solver" or + solver_type.lower() == "twophase"): + custom_settings["solver_settings"]["time_stepping"].AddValue("end_time", custom_settings["problem_data"]["end_time"]) + solver_module_name = "geomechanics_U_Pw_solver" + + else: + err_msg = "The requested solver type \"" + solver_type + "\" is not in the python solvers wrapper\n" + err_msg += "Available options are: \"geomechanics_U_Pw_solver\"" + raise Exception(err_msg) + + # Solvers for MPI parallelism + elif (parallelism == "MPI"): + if (solver_type.lower() == "dynamic"): + time_integration_method = custom_settings["solver_settings"]["time_integration_method"].GetString() + if (time_integration_method == "implicit"): + solver_module_name = "trilinos_geomechanics_implicit_dynamic_solver" + else: + err_msg = "The requested time integration method \"" + time_integration_method + "\" is not in the python solvers wrapper\n" + err_msg += "Available options are: \"implicit\"" + raise Exception(err_msg) + + else: + err_msg = "The requested solver type \"" + solver_type + "\" is not in the python solvers wrapper\n" + raise Exception(err_msg) + else: + err_msg = "The requested parallel type \"" + parallelism + "\" is not available!\n" + err_msg += "Available options are: \"OpenMP\", \"MPI\"" + raise Exception(err_msg) + + module_full_name = 'KratosMultiphysics.GeoMechanicsApplication.' + solver_module_name + solver = import_module(module_full_name).CreateSolver(model, custom_settings["solver_settings"]) + + return solver diff --git a/applications/GeoMechanicsApplication/python_scripts/run_multiple_stages.py b/applications/GeoMechanicsApplication/python_scripts/run_multiple_stages.py new file mode 100644 index 000000000000..db9c4f4de5fb --- /dev/null +++ b/applications/GeoMechanicsApplication/python_scripts/run_multiple_stages.py @@ -0,0 +1,40 @@ +import sys +import os + +sys.path.append(os.path.join('..', '..', '..')) + +import KratosMultiphysics as Kratos +from KratosMultiphysics.GeoMechanicsApplication import * +import KratosMultiphysics.GeoMechanicsApplication.geomechanics_analysis as analysis + + +def run_stages(project_path,n_stages): + """ + Run all construction stages + + :param project_path: + :param n_stages: + :return: + """ + parameter_file_names = [os.path.join(project_path, 'ProjectParameters_stage' + str(i + 1) + '.json') for i in + range(n_stages)] + + # set stage parameters + parameters_stages = [None] * n_stages + os.chdir(project_path) + for idx, parameter_file_name in enumerate(parameter_file_names): + with open(parameter_file_name, 'r') as parameter_file: + parameters_stages[idx] = Kratos.Parameters(parameter_file.read()) + + model = Kratos.Model() + stages = [analysis.GeoMechanicsAnalysis(model, stage_parameters) for stage_parameters in parameters_stages] + + [stage.Run() for stage in stages] + + +if __name__ == "__main__": + + n_stages = 11 + project_path = r"C:\Users\noordam\Documenten\Kratos\applications\GeoMechanicsApplication\test_examples\1D-Consolidation_all_stages" + + run_stages(project_path, n_stages) \ No newline at end of file diff --git a/applications/HDF5Application/CMakeLists.txt b/applications/HDF5Application/CMakeLists.txt index 1a3fc200186d..fd3b7bf9ab56 100644 --- a/applications/HDF5Application/CMakeLists.txt +++ b/applications/HDF5Application/CMakeLists.txt @@ -6,23 +6,24 @@ include_directories( ${KRATOS_SOURCE_DIR}/kratos ) # generate variables with the sources set( KRATOS_HDF5_APPLICATION_CORE - ${CMAKE_CURRENT_SOURCE_DIR}/hdf5_application.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/hdf5_application_variables.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_file.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_file_serial.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_model_part_io.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_properties_io.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_data_value_container_io.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_nodal_solution_step_variables_io.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_nodal_solution_step_data_io.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_nodal_solution_step_bossak_io.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_points_data.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_connectivities_data.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_container_component_io.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_processes/hdf5_xdmf_connectivities_writer_process.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/hdf5_data_set_partition_utility.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/factor_elements_and_conditions_utility.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/local_ghost_splitting_utility.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hdf5_application.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hdf5_application_variables.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_file.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_file_serial.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_model_part_io.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_properties_io.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_data_value_container_io.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_nodal_solution_step_variables_io.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_nodal_solution_step_data_io.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_nodal_solution_step_bossak_io.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_points_data.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_connectivities_data.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_container_component_io.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_io/hdf5_container_gauss_point_output.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_processes/hdf5_xdmf_connectivities_writer_process.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/hdf5_data_set_partition_utility.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/factor_elements_and_conditions_utility.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/custom_utilities/local_ghost_splitting_utility.cpp ) ## HDF5Application python interface sources @@ -100,6 +101,12 @@ pybind11_add_module(KratosHDF5Application MODULE THIN_LTO ${KRATOS_HDF5_APPLICAT target_link_libraries(KratosHDF5Application PRIVATE KratosHDF5Core) set_target_properties(KratosHDF5Application PROPERTIES PREFIX "") +# Set batch size in the unity build +IF(CMAKE_UNITY_BUILD MATCHES ON) + set_target_properties(KratosHDF5Core PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) + set_target_properties(KratosHDF5Application PROPERTIES UNITY_BUILD_BATCH_SIZE ${KRATOS_UNITY_BUILD_BATCH_SIZE}) +ENDIF(CMAKE_UNITY_BUILD MATCHES ON) + # changing the .dll suffix to .pyd (Windows) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set_target_properties(KratosHDF5Application PROPERTIES SUFFIX .pyd) @@ -110,12 +117,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(KratosHDF5Application PROPERTIES SUFFIX .so) endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -# Cotire -if(USE_COTIRE MATCHES ON) - cotire(KratosHDF5Core) - cotire(KratosHDF5Application) -endif(USE_COTIRE MATCHES ON) - # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/HDF5Application.py KratosMultiphysics/HDF5Application/__init__.py ) diff --git a/applications/HDF5Application/README.md b/applications/HDF5Application/README.md index 348d056e24c3..0ec2e33005a3 100644 --- a/applications/HDF5Application/README.md +++ b/applications/HDF5Application/README.md @@ -71,6 +71,8 @@ There are few available HDF5 processes which can be integrated into work flow vi This process can be used to initialize a given model part using existing HDF5 files. Illustrated example reads in VELOCITY and PRESSURE variables from "hdf5_output/example_initialization_file.h5" file to nodal historical data value container, and nodal, elemental and condition non-historical data value containers. This process also can read FLAGS from HDF5 file and populate model part accordingly. +For the ```list_of_variables``` in either ```nodal_data_value_settings```, ```element_data_value_settings```, ```condition_data_value_settings``` one can specify ```ALL_VARIABLES_FROM_FILE``` which will read all the variables available in the input hdf5 file and will populate the model part accordingly. This ```ALL_VARIABLES_FROM_FILE``` should be used alone (There can be only this entry in the list if it is used). + ```json { "kratos_module": "KratosMultiphysics.HDF5Application", @@ -128,6 +130,8 @@ This process can be used to initialize a given model part using existing HDF5 fi This process is used to initialize model part variables at each time step from hdf5 files. You can specify the list of hdf5 files to read from by changing the "file_name" with tags ```